Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using margin on flex items

Tags:

css

flexbox

I was under the impression that a margin can be added to flex items/children, and flexbox should automatically take that into account and calculate the correct spacing between the items.

I can't seem to get this working as I would like though.

Fiddle here: https://jsfiddle.net/dba5ehcw/1/

.flex-item{     border: 1px solid blue;     box-sizing: border-box;     height: 160px;     width: 50%; } 

So each flex item at the moment is half the width of the container, and they flow nicely next to each other.

I would like to be able to add a margin of say, 1em to the flex-items in order to give them some breathing room, but in doing so, they become larger than the 50% and no longer stack next to each other on the same line because they are too wide.

Is there a way to use margin on the flex-items and have the flexbox container take this into account and adjust (decrease) their widths accordingly?

like image 994
Luke Twomey Avatar asked Sep 24 '15 15:09

Luke Twomey


People also ask

How does margin right auto work?

The percentage is based on the width of the container. margin-right: auto; The auto keyword will give the right side a share of the remaining space. When combined with margin-left: auto , it will center the element, if a fixed width is defined.

What happens when margin Auto is applied on a span of fixed height?

It guarantees that the left and right margins will be set to the same size.


2 Answers

There are multiple ways to do this:

  • Use calc:

    .flex-item {   width: calc(50% - 2em);   margin: 1em; } 

    .flex-container {    border: 1px solid red;    box-sizing: border-box;    display: flex;    flex-wrap: wrap;    width: 320px;  }  .flex-item {    border: 1px solid blue;    box-sizing: border-box;    height: calc(160px - 2em);    width: calc(50% - 2em);    margin: 1em;  }
    <div class="flex-container">    <div class="flex-item"></div>    <div class="flex-item"></div>    <div class="flex-item"></div>    <div class="flex-item"></div>    <div class="flex-item"></div>    <div class="flex-item"></div>  </div>
  • Use nested boxes:

    .flex-item {   width: 50%;   display: flex; } .flex-item > div {   border: 1px solid blue;   flex: 1;   margin: 1em; } 

    .flex-container {    border: 1px solid red;    box-sizing: border-box;    display: flex;    flex-wrap: wrap;    width: 320px;  }  .flex-item {    height: 160px;    width: 50%;    display: flex;  }  .flex-item > div {    border: 1px solid blue;    flex: 1;    margin: 1em;  }
    <div class="flex-container">    <div class="flex-item"><div></div></div>    <div class="flex-item"><div></div></div>    <div class="flex-item"><div></div></div>    <div class="flex-item"><div></div></div>    <div class="flex-item"><div></div></div>    <div class="flex-item"><div></div></div>  </div>
  • Place each row in a nowrap container, and use a positive flex-shrink factor

    .row {   display: flex; } .flex-item {   width: 50%;   margin: 1em; } 

    .flex-container {    border: 1px solid red;    width: 320px;  }  .row {    height: 160px;    display: flex;  }  .flex-item {    border: 1px solid blue;    width: 50%;    margin: 1em;  }
    <div class="flex-container">    <div class="row">      <div class="flex-item"></div>      <div class="flex-item"></div>    </div>    <div class="row">      <div class="flex-item"></div>      <div class="flex-item"></div>    </div>    <div class="row">      <div class="flex-item"></div>      <div class="flex-item"></div>    </div>  </div>
  • Don't use width. Instead, force line-breaks at the right places, and use flex: 1 to make the elements grow to fill remaining space.

    .flex-item {   flex: 1; } .line-break {   width: 100% } 

    .flex-container {    border: 1px solid red;    box-sizing: border-box;    display: flex;    flex-wrap: wrap;    width: 320px;  }  .flex-item {    border: 1px solid blue;    box-sizing: border-box;    height: calc(160px - 2em);    flex: 1;    margin: 1em;  }  .line-break {    width: 100%;  }
    <div class="flex-container">    <div class="flex-item"></div>    <div class="flex-item"></div>    <div class="line-break"></div>    <div class="flex-item"></div>    <div class="flex-item"></div>    <div class="line-break"></div>    <div class="flex-item"></div>    <div class="flex-item"></div>  </div>
like image 61
Oriol Avatar answered Oct 20 '22 06:10

Oriol


You need to do it with padding - which, when in border-box mode does not make the container larger than it's specified width - not margin, and a nested flex div. This is how all flexbox-based grid systems work. Code below:

.flex-container{      border: 1px solid red;      box-sizing: border-box;      display: flex;      flex-wrap: wrap;      width: 320px;  }    .flex-item{      padding:1em;      box-sizing: border-box;      height: 160px;      width: 50%;      display:flex;  }    .flex-item>div {      border: 1px solid blue;      flex: 1 1 auto;  }
<div class="flex-container">      <div class="flex-item"><div></div></div>      <div class="flex-item"><div></div></div>      <div class="flex-item"><div></div></div>      <div class="flex-item"><div></div></div>      <div class="flex-item"><div></div></div>      <div class="flex-item"><div></div></div>  </div>
like image 23
Adam Avatar answered Oct 20 '22 06:10

Adam