Equal separation between elements in a div - html

Let's say I have a div, 100px wide, and a variable number (from 1 to 6) of elements, 10px wide, inside that div.
How can I equally space them so that:
if there is 1 element inside, there will be no additional spacing
if there are from 2 to 6 elements, spacing between each would be 80px (for 2), 35px (for 3), 20px (for 4), etc...
The first item will always be placed at the most left position, without padding, and the last item will always be placed at the most right position, also without padding.
I'm not concerned about IE, so this could be CSS3. Anyways, I am concerned about javascript. I know this would be a 1 liner in JS, but I certainly want to avoid it if possible, so please refrain answering if you're going to post a JS solution.
Regards
Edit:
Example: http://codepen.io/anon/pen/wbiFA
HTML
<div class="container">
<div class="item">
</div>
<div class="item">
</div>
<div class="item">
</div>
<div class="item">
</div>
</div>
CSS:
.container {
width: 900px;
border: 1px solid red;
display: flex;
justify-content: space-between;
height: 50px;
}
.item {
border: 1px solid blue;
flex-basis: auto;
width: 171px
}
Ok, did it :)

You don't need CSS3 features like flexible boxes. The following CSS2.1 features are enough:
text-align:justify
display: inline-block
::after pseudo-element
.container {
width: 900px;
border: 1px solid red;
height: 50px;
text-align: justify;
}
.container:after {
content: '';
width: 100%;
display: inline-block;
}
.item {
border: 1px solid blue;
width: 171px;
height: 100%;
display: inline-block;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>

Using Flexbox i managed a close enough result:
http://codepen.io/coljung/pen/bufmh
.container {
border: 1px solid red;
width:1000px;
height:100px;
display: flex;
justify-content: space-around;
}
.item {
border: 1px solid blue;
background:red;
width:100px;
height:100%;
}
Now, it doesnt achieve the exact padding you are looking for. In that case you have to do it manually for every single case.

Related

CSS Flexbox float elements [duplicate]

This question already has answers here:
Is it possible for flex items to align tightly to the items above them?
(5 answers)
Make a div span two rows in a grid
(2 answers)
Closed 5 years ago.
I'm trying to float two elements at the right of a "figure" element using flex but it end up floating just div1 at the right of figure and div2 is moved bellow, if I make div1 and div2 narrow enough, they are floated inline at the right of figure.
This is the CSS:
.container {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
}
Desired Result:
Actual Result:
How it works?
First, you make a flex-container (flexc in this case) and apply the display:flex property on it which aligns the elements by default in row alignment. If you want an element to preserve its dimensions set it to flex:0 0 auto; else you can make use of flex:1; which shrinks or grows as the browser is resized.
Then to align the contents in column (div1 and div2) you can just wrap then in a different container and since div isn't an inline container, and the flex property doesn't have any effect on any other than the direct children of the flex parent, they are aligned in seperate lines.
.flexc {
display: flex;
justify-content: flex-start;
}
#fig {
flex: 0 0 auto;
width: 200px;
height: 200px;
background: gray;
text-align: center;
color: white;
margin: 10px;
border: 2px solid black;
}
#d1,
#d2 {
width: 200px;
height: 50px;
background: purple;
text-align: center;
color: white;
margin: 10px;
border: 2px solid black;
}
<div class="flexc">
<div id="fig">Figure</div>
<div class="col">
<div id="d1">div1</div>
<div id="d2">div2</div>
</div>
</div>
Without altering the html:
.flexc {
display: flex;
flex-direction:column;
position:relative;
}
#fig {
flex: 0 0 auto;
width: 200px;
height: 200px;
background: gray;
text-align: center;
color: white;
margin: 10px;
border: 2px solid black;
}
#d1,
#d2 {
position:absolute;
left:250px;
width: 200px;
height: 50px;
background: purple;
text-align: center;
color: white;
margin: 10px;
border: 2px solid black;
}
#d2{
top:70px;
}
<div class="flexc">
<div id="fig">Figure</div>
<div id="d1">div1</div>
<div id="d2">div2</div>
</div>
Not sure what your HTML looks like, but display: flex is best used on the container wrapping all the elements you want aligned. Imagine it to be the largest box that you put smaller boxes inside.
Codepen example demonstrating this: https://codepen.io/corviday/pen/VyYdar
Following this hierarchy with .container as your largest box, since you want two columns, you can divide it further into two smaller boxes (.left in red and .right in blue in this case).
From there you would need to group div1/div2 together to float the way you'd like, and would be the items that fill the box .right.
You can use Bootstrap to resolve or put div1 and div2 in one div main to drop div main
Bootstrap exemple
<div class='container'>
<div class="col-md-12">
<div class="col-md-6">
1 text
</div>
<div class="col-md-6">
<div class="col-md-6">
2 text
</div>
<div class="col-md-6">
3 text
</div>
</div>
</div>
</div>
I think the best layout engine to use for your use case is hinted at in your description of the problem: Floats.
Here is a solution that doesn't require you to alter your html.
<div class="container">
<div class="medium-box">figure</div>
<div class="small-box">div 1</div>
<div class="small-box">div 2</div>
</div>
.container{
width: 500px;
}
.medium-box {
height: 200px;
width: 200px;
margin: 10px;
background: grey;
float:left
}
.small-box {
float:left;
height: 30px;
width: 200px;
background: blue;
margin: 10px;
}
https://codepen.io/stacyvlasits/pen/aVPZbY

FlexBox - container width not expanding when using percent margin [duplicate]

This question already has answers here:
Why doesn't percentage padding / margin work on flex items in Firefox and Edge?
(2 answers)
Closed 5 years ago.
I built a simple page using FlexBox CSS, and I don't understand why when I use a percent margin on one of the items, the width of the container is not expanding.
Note: Problems exists in Chrome / FireFox.
Code Pen: https://codepen.io/dsomekh/pen/QvGvrq
Example:
<html>
<style>
.page{
display:flex;
/*border: 5px solid orange;*/
}
.container{
display:flex;
border: 5px solid orange;
}
.item_left{
display:flex;
margin-right:25%;
}
.item_right{
display:flex;
}
</style>
<div class="page">
<div class="container">
<div class="item_left">Left</div>
<div class="item_right">Right</div>
</div>
</div>
</html>
You're using flexbox wrong.
try
.container{
display:flex;
}
.item_left {
flex: 1;
border: 5px solid orange;
margin-right:25%;
}
.item_right {
flex: 1;
border: 5px solid orange;
}
<div class="page">
<div class="container">
<div class="item_left">Left</div>
<div class="item_right">Right</div>
</div>
</div>
As Michael Coker commented, Authors should avoid using percentages in paddings or margins on flex items entirely, as they will get different behavior in different browsers. (CSS Flexbox margins)
When using percent we often relate that to the viewport width, so with that in mind, viewport units vw/vh can be a good option, since it works similar (responsive).
Stack snippet made of your Codepen sample
.page {
display: flex;
/*border: 5px solid orange;*/
}
.container {
display: flex;
border: 5px solid orange;
}
.item_left {
flex: 1;
margin-right: 25vw;
}
.item_right {
display: flex;
flex: 1;
}
<div class="page">
<div class="container">
<div class="item_left">Left</div>
<div class="item_right">Right</div>
</div>
</div>
Stack snippet made of your questions code
.page {
display: flex;
/*border: 5px solid orange;*/
}
.container {
display: flex;
border: 5px solid orange;
}
.item_left {
display: flex;
margin-right: 25vw;
}
.item_right {
display: flex;
}
<div class="page">
<div class="container">
<div class="item_left">Left</div>
<div class="item_right">Right</div>
</div>
</div>

Aligning horizontal borders across a grid

I am using something similar to css wizardry grids. I am trying to align horizontal borders across seperate grid items. The image at the top is always the same size. For the most part the seperate borders line up However because the grid works in percentages that are finer than a pixel, at some screen sizes the borders dis-align (see Blog Article 3 below).
I can't just use a <hr> because on smaller screensizes the grid condenses to to on a row and then one on a row. I need a responsive solution that doesn't use javascript. I don't necessarily need a code example of how to do this but an approach.
You can consider display:flex
.container {
display: flex;
justify-content: space-between;
width: 50%;
}
.container .item {
background: green;
border: 1px solid black;
width: 50px;
height: 50px;
}
.bb {
display: flex;
justify-content: space-between;
border-top: 1px solid black;
padding: 10px;
border-bottom: 1px solid black;
margin-top: 20px;
width: 50%;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="bb">
<div>
item1
</div>
<div>
item2
</div>
<div>
item3
</div>
</div>
Hope this helps

How to use flex to align button with centered text but icon to one side? [duplicate]

I'm using flexbox to align my child elements. What I'd like to do is center one element and leave the other aligned to the very left. Normally I would just set the left element using margin-right: auto. The problem is that pushes the center element off center. Is this possible without using absolute positioning?
HTML & CSS
#parent {
align-items: center;
border: 1px solid black;
display: flex;
justify-content: center;
margin: 0 auto;
width: 500px;
}
#left {
margin-right: auto;
}
#center {
margin: auto;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
Add third empty element:
<div class="parent">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right"></div>
</div>
And the following style:
.parent {
display: flex;
}
.left, .right {
flex: 1;
}
Only left and right are set to grow and thanks to the facts that...
there are only two growing elements (doesn't matter if empty) and
that both get same widths (they'll evenly distribute the available space)
...center element will always be perfectly centered.
This is much better than accepted answer in my opinion because you do not have to copy left content to right and hide it to get same width for both sides, it just magically happens (flexbox is magical).
In action:
.parent {
display: flex;
}
.left,
.right {
flex: 1;
}
/* Styles for demonstration */
.parent {
padding: 5px;
border: 2px solid #000;
}
.left,
.right {
padding: 3px;
border: 2px solid red;
}
.center {
margin: 0 3px;
padding: 3px;
border: 2px solid blue;
}
<div class="parent">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right"></div>
</div>
EDIT: See Solo's answer below, it is the better solution.
The idea behind flexbox is to provide a framework for easily aligning elements with variable dimensions within a container. As such, it makes little sense to provide a layout where the width of one element is totally ignored. In essence, that is exactly what absolute positioning is for, as it takes the element out of the normal flow.
As far as I know, there is no nice way of doing this without using position: absolute;, so I would suggest using it... but If you REALLY don't want to, or can't use absolute positioning then I suppose you could use one of the following workarounds.
If you know the exact width of the "Left" div, then you could change justify-content to flex-start (left) and then align the "Center" div like this:
#center {
position: relative;
margin: auto;
left: -{half width of left div}px;
}
If you do not know the width, then you could duplicate "Left" on the right side, use justify-content: space-between;, and hide the new right element:
Just to be clear, this is really, really ugly... better to use absolute positioning than to duplicate content. :-)
#parent {
align-items: center;
border: 1px solid black;
display: flex;
justify-content: space-between;
margin: 0 auto;
width: 500px;
}
#right {
opacity: 0;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
<span id="right">Left</span>
</div>
.parent {
display: flex;
}
.left {
flex: 1;
}
.parent::after {
flex: 1;
content: '';
}
<div class="parent">
<div class="left">Left</div>
<div>Center</div>
</div>
I have another solution. In my opinion, Adding an empty block to the center element is fine but code-wise it bit ugly.
Since this is 4 years old I figured I'd update this with a much easier CSS Grid solution.
#parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
border: 1px solid black;
margin: 0 auto;
width: 500px;
}
#center {
text-align: center;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
If you don't want to rely on positioning, the only way I've found that makes it truly centered is to use a combination of auto margin and negative margin prevent the centered element to getting pushed over by the left aligned element. This requires that you know the exact width of the left aligned element though.
.container {
height: 100px;
border: solid 10px skyblue;
display: flex;
justify-content: center;
}
.block {
width: 120px;
background: tomato;
}
.justify-start {
margin-right: auto;
}
.justify-center {
margin-right: auto;
margin-left: -120px;
}
<div class="container">
<div class="block justify-start"></div>
<div class="block justify-center"></div>
</div>
As far as I know this is possible with the following code.
https://jsfiddle.net/u5gonp0a/
.box {
display: flex;
justify-content: center;
background-color: green;
text-align: left;
}
.left {
padding: 10px;
background-color: pink;
}
.center {
padding: 10px;
background-color: yellow;
margin: 0 auto;
}
<div class="box">
<div class="left">left</div>
<div class="center">center</div>
</div>
Try this no hacks :)
CSS
.container{
width: 500px;
margin: 0 auto;
}
.box{
display: flex;
align-items: center;/* just in case*/
justify-content: space-between;
}
.box p:nth-child(2){
text-align: center;
background-color: lime;
flex: 1 1 0px;
}
HTML
<div class="container">
<div class="box">
<p>One</p>
<p>Two</p>
</div>
</div>
http://codepen.io/whisher/pen/XpGaEZ
If you have a grid system you can use it to do what you want without "extra" css.
Below with bootstrap (V 4.X)
Note: It uses flex under the hood
<div class="row">
<div class="col text-left">left</col>
<div class="col text-center">center</col>
<div class="col text-right">right</col>
</div>
Doc bootstrap: https://getbootstrap.com/docs/4.6/layout/grid/
Et voilĂ  ! :)
Solution 1: give 50% width to center element and use justify-content:space-between
#parent {
display: flex;
justify-content: space-between;
}
#center {
flex-basis: 50%;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
Solution 2: Add one dummy element and hide it.
#parent {
display: flex;
justify-content: space-between;
}
#right {
visibility:hidden;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
<span id="right">Right</span>
</div>

2 Inner divs - one should be center and not collide with the other [duplicate]

I'm using flexbox to align my child elements. What I'd like to do is center one element and leave the other aligned to the very left. Normally I would just set the left element using margin-right: auto. The problem is that pushes the center element off center. Is this possible without using absolute positioning?
HTML & CSS
#parent {
align-items: center;
border: 1px solid black;
display: flex;
justify-content: center;
margin: 0 auto;
width: 500px;
}
#left {
margin-right: auto;
}
#center {
margin: auto;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
Add third empty element:
<div class="parent">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right"></div>
</div>
And the following style:
.parent {
display: flex;
}
.left, .right {
flex: 1;
}
Only left and right are set to grow and thanks to the facts that...
there are only two growing elements (doesn't matter if empty) and
that both get same widths (they'll evenly distribute the available space)
...center element will always be perfectly centered.
This is much better than accepted answer in my opinion because you do not have to copy left content to right and hide it to get same width for both sides, it just magically happens (flexbox is magical).
In action:
.parent {
display: flex;
}
.left,
.right {
flex: 1;
}
/* Styles for demonstration */
.parent {
padding: 5px;
border: 2px solid #000;
}
.left,
.right {
padding: 3px;
border: 2px solid red;
}
.center {
margin: 0 3px;
padding: 3px;
border: 2px solid blue;
}
<div class="parent">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right"></div>
</div>
EDIT: See Solo's answer below, it is the better solution.
The idea behind flexbox is to provide a framework for easily aligning elements with variable dimensions within a container. As such, it makes little sense to provide a layout where the width of one element is totally ignored. In essence, that is exactly what absolute positioning is for, as it takes the element out of the normal flow.
As far as I know, there is no nice way of doing this without using position: absolute;, so I would suggest using it... but If you REALLY don't want to, or can't use absolute positioning then I suppose you could use one of the following workarounds.
If you know the exact width of the "Left" div, then you could change justify-content to flex-start (left) and then align the "Center" div like this:
#center {
position: relative;
margin: auto;
left: -{half width of left div}px;
}
If you do not know the width, then you could duplicate "Left" on the right side, use justify-content: space-between;, and hide the new right element:
Just to be clear, this is really, really ugly... better to use absolute positioning than to duplicate content. :-)
#parent {
align-items: center;
border: 1px solid black;
display: flex;
justify-content: space-between;
margin: 0 auto;
width: 500px;
}
#right {
opacity: 0;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
<span id="right">Left</span>
</div>
.parent {
display: flex;
}
.left {
flex: 1;
}
.parent::after {
flex: 1;
content: '';
}
<div class="parent">
<div class="left">Left</div>
<div>Center</div>
</div>
I have another solution. In my opinion, Adding an empty block to the center element is fine but code-wise it bit ugly.
Since this is 4 years old I figured I'd update this with a much easier CSS Grid solution.
#parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
border: 1px solid black;
margin: 0 auto;
width: 500px;
}
#center {
text-align: center;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
If you don't want to rely on positioning, the only way I've found that makes it truly centered is to use a combination of auto margin and negative margin prevent the centered element to getting pushed over by the left aligned element. This requires that you know the exact width of the left aligned element though.
.container {
height: 100px;
border: solid 10px skyblue;
display: flex;
justify-content: center;
}
.block {
width: 120px;
background: tomato;
}
.justify-start {
margin-right: auto;
}
.justify-center {
margin-right: auto;
margin-left: -120px;
}
<div class="container">
<div class="block justify-start"></div>
<div class="block justify-center"></div>
</div>
As far as I know this is possible with the following code.
https://jsfiddle.net/u5gonp0a/
.box {
display: flex;
justify-content: center;
background-color: green;
text-align: left;
}
.left {
padding: 10px;
background-color: pink;
}
.center {
padding: 10px;
background-color: yellow;
margin: 0 auto;
}
<div class="box">
<div class="left">left</div>
<div class="center">center</div>
</div>
Try this no hacks :)
CSS
.container{
width: 500px;
margin: 0 auto;
}
.box{
display: flex;
align-items: center;/* just in case*/
justify-content: space-between;
}
.box p:nth-child(2){
text-align: center;
background-color: lime;
flex: 1 1 0px;
}
HTML
<div class="container">
<div class="box">
<p>One</p>
<p>Two</p>
</div>
</div>
http://codepen.io/whisher/pen/XpGaEZ
If you have a grid system you can use it to do what you want without "extra" css.
Below with bootstrap (V 4.X)
Note: It uses flex under the hood
<div class="row">
<div class="col text-left">left</col>
<div class="col text-center">center</col>
<div class="col text-right">right</col>
</div>
Doc bootstrap: https://getbootstrap.com/docs/4.6/layout/grid/
Et voilĂ  ! :)
Solution 1: give 50% width to center element and use justify-content:space-between
#parent {
display: flex;
justify-content: space-between;
}
#center {
flex-basis: 50%;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
Solution 2: Add one dummy element and hide it.
#parent {
display: flex;
justify-content: space-between;
}
#right {
visibility:hidden;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
<span id="right">Right</span>
</div>