In the snippet below, the first row has two divs with flex-grow: 1
. As expected, each div takes up 50% of the screen.
When adding padding to the left div, that is no longer the case. Can someone explain why?
A flex item's size with padding and flex-grow
is determined by calculations in the flexbox spec.
These calculations are similar to the sizing of flex items with padding and flex-shrink
.
Frankly, the math is quite technical and not the easiest thing in the world to understand.
But if you want to get into it, here are the details:
Below are examples that hopefully make the behavior more clear.
NOTE: Keep in mind that flex-grow
is not a tool for directly establishing the length of a flex item. It's a tool for distributing space in the container among flex items. The flex-basis
property sets the initial main size of a flex item. If flex-grow
is used with flex-basis
, the problem in the question is resolved (see example #4 below).
Example #1
In a block container, where you have box-sizing: border-box
, the boxes in your code will render evenly regardless of padding.
body > div {
height: 50px;
/* display: flex; */
font-size: 0; /* remove inline block whitespace */
}
body > div > div {
/* flex: 1; */
box-sizing: border-box;
height: 50px;
display: inline-block;
width: 50%;
}
#a {
background-color: red;
}
#b {
background-color: green;
}
#c {
padding: 10px;
background-color: blue;
}
#d {
background-color: yellow;
<div>
<div id="a"></div>
<div id="b"></div>
</div>
<div>
<div id="c"></div>
<div id="d"></div>
</div>
Example #2
In a flex container, where you have box-sizing: border-box
, and the width
or flex-basis
is used to calculate length, the boxes will render evenly regardless of padding.
body > div {
height: 50px;
display: flex;
}
body > div > div {
flex-basis: 50%;
/* width: 50%; this works, as well */
box-sizing: border-box;
}
#a {
background-color: red;
}
#b {
background-color: green;
}
#c {
padding: 10px;
background-color: blue;
}
#d {
background-color: yellow;
<div>
<div id="a"></div>
<div id="b"></div>
</div>
<div>
<div id="c"></div>
<div id="d"></div>
</div>
Example #3
In a flex container, where you have box-sizing: border-box
and flex-grow
, it will appear that box-sizing
doesn't work...
body > div {
height: 50px;
display: flex;
}
body > div > div {
flex: 1;
/* flex-basis: 50%; */
/* width: 50%; this works, as well */
box-sizing: border-box;
}
#a {
background-color: red;
}
#b {
background-color: green;
}
#c {
padding: 10px;
background-color: blue;
}
#d {
background-color: yellow;
<div>
<div id="a"></div>
<div id="b"></div>
</div>
<div>
<div id="c"></div>
<div id="d"></div>
</div>
but that's not really correct...
Example #4
flex-grow
expands the width of a flex item based on available space in the flex container. In other words, it ignores padding (and borders).
However, if you simply specify flex-grow
along with flex-basis
, the border-box
will work:
flex: 1 1 50%; /* flex-grow, flex-shrink, flex-basis */
body > div {
height: 50px;
display: flex;
}
body > div > div {
flex: 1 1 50%; /* flex-grow, flex-shrink, flex-basis */
/* flex-basis: 50%; */
/* width: 50%; this works, as well */
box-sizing: border-box;
}
#a {
background-color: red;
}
#b {
background-color: green;
}
#c {
padding: 10px;
background-color: blue;
}
#d {
background-color: yellow;
<div>
<div id="a"></div>
<div id="b"></div>
</div>
<div>
<div id="c"></div>
<div id="d"></div>
</div>