Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is padding expanding a flex item?

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?

body > div {    height: 50px;    display: flex;  }  body > div > div {    flex: 1;    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>
like image 558
Yair Avatar asked Oct 15 '15 09:10

Yair


People also ask

Does padding work with flexbox?

You do have to make sure that the padding on the ::after pseudo-element is half that of the padding used on the flex container, because padding is applied all around the pseudo-element. But if you go with padding-left or padding-right , then you can use the same value as the padding on the flex container.

How do I stop my flex from stretching CSS?

By default, the child elements of a flexbox container will stretch vertically to fill the height of the container. This can be prevented by using the align-self property on the child element that you do not want to stretch.

How do you use padding on flexbox?

Padding between flexbox items can be accomplished by setting the 'justify-content' property to 'space-between'. This will cause the items to evenly distribute themselves within the container, with the first item flush with the left side of the container and the last item flush with the right side.


2 Answers

The calculations are defined in the spec.

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:

  • 9.7. Resolving Flexible Lengths
  • How does flex-shrink factor in padding and border-box?

Examples

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>

jsFiddle demo


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>

jsFiddle demo


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>

jsFiddle demo

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>

jsFiddle demo

like image 101
Michael Benjamin Avatar answered Sep 24 '22 21:09

Michael Benjamin


That's the correct behaviour as far as I am aware.

flex:1 is, of course, shorthand for:

flex-grow:1; flex-shrink:1; flex-basis:0 

This allows the div to grow if necessary which, in this case, it does. It's not automatically going to maintain the flex-items as all the same size if they are, in fact, different.

like image 22
Paulie_D Avatar answered Sep 23 '22 21:09

Paulie_D