[css] Better way to set distance between flexbox items

To set the minimal distance between flexbox items I'm using margin: 0 5px on .item and margin: 0 -5px on container. For me it seems like a hack, but I can't find any better way to do this.

Example

_x000D_
_x000D_
#box {_x000D_
  display: flex;_x000D_
  width: 100px;_x000D_
  margin: 0 -5px;_x000D_
}_x000D_
.item {_x000D_
  background: gray;_x000D_
  width: 50px;_x000D_
  height: 50px;_x000D_
  margin: 0 5px;_x000D_
}
_x000D_
<div id='box'>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

This question is related to css flexbox

The answer is


A flex container with -x (negative) margin and flex items with x (positive) margin or padding both lead to the desired visual result: Flex items have a fixed gap of 2x only between each other.

It appears to be simply a matter of preference, whether to use margin or padding on the flex items.

In this example, the flex items are scaled dynamically in order to preserve the fixed gap:

.flex-container { 
  margin: 0 -5px;
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.flex-item {
  margin: 0 5px; // Alternatively: padding: 0 5px;
  flex: 1 0 auto;
}

Moving on from sawa's answer, here's a slightly improved version that allows you to set a fixed spacing between the items without the surrounding margin.

http://jsfiddle.net/chris00/s52wmgtq/49/

Also included is the Safari "-webkit-flex" version.

.outer1 {
    background-color: orange;
    padding: 10px;
}

.outer0 {
    background-color: green;
    overflow: hidden;
}

.container
{
    display: flex;
    display: -webkit-flex;
    flex-wrap: wrap;    
    -webkit-flex-wrap: wrap;
    background-color: rgba(0, 0, 255, 0.5);
    margin-left: -10px;
    margin-top: -10px;
}

.item
{
    flex-grow: 1;
    -webkit-flex-grow: 1;
    background-color: rgba(255, 0, 0, 0.5);
    width: 100px;
    padding: 10px;
    margin-left: 10px;
    margin-top: 10px;
    text-align: center;
    color: white;
}

<div class="outer1">
    <div class="outer0">
        <div class="container">
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
        </div>
    </div>
</div>

You can use & > * + * as a selector to emulate a flex-gap (for a single line):

_x000D_
_x000D_
#box { display: flex; width: 230px; outline: 1px solid blue; }_x000D_
.item { background: gray; width: 50px; height: 100px; }_x000D_
_x000D_
/* ----- Flexbox gap: ----- */_x000D_
_x000D_
#box > * + * {_x000D_
  margin-left: 10px;_x000D_
}
_x000D_
<div id='box'>_x000D_
    <div class='item'></div>_x000D_
    <div class='item'></div>_x000D_
    <div class='item'></div>_x000D_
    <div class='item'></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

If you need to support flex wrapping, you can use a wrapper element:

_x000D_
_x000D_
.flex { display: flex; flex-wrap: wrap;  }_x000D_
.box { background: gray; height: 100px; min-width: 100px; flex: auto; }_x000D_
.flex-wrapper {outline: 1px solid red; }_x000D_
_x000D_
/* ----- Flex gap 10px: ----- */_x000D_
_x000D_
.flex > * {_x000D_
  margin: 5px;_x000D_
}_x000D_
.flex {_x000D_
  margin: -5px;_x000D_
}_x000D_
.flex-wrapper {_x000D_
  width: 400px; /* optional */_x000D_
  overflow: hidden; /* optional */_x000D_
}
_x000D_
<div class='flex-wrapper'>_x000D_
  <div class='flex'>_x000D_
    <div class='box'></div>_x000D_
    <div class='box'></div>_x000D_
    <div class='box'></div>_x000D_
    <div class='box'></div>_x000D_
    <div class='box'></div>_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


You can try CSS3's :not selector

Eg:

_x000D_
_x000D_
#box {_x000D_
  display: flex;_x000D_
  width: 100px;_x000D_
  border: 1px red solid;_x000D_
}_x000D_
_x000D_
.item {_x000D_
  background: gray;_x000D_
  width: 10px;_x000D_
  height: 100px;_x000D_
  flex: 1 1 auto;_x000D_
}_x000D_
_x000D_
.item:not(:last-child) {_x000D_
  margin-right: 5px;_x000D_
}
_x000D_
<div id='box'>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


I often use the + operator for such cases

_x000D_
_x000D_
#box {_x000D_
  display: flex;_x000D_
  width: 100px;_x000D_
}_x000D_
.item {_x000D_
  background: gray;_x000D_
  width: 50px;_x000D_
  height: 50px;_x000D_
}_x000D_
.item + .item {_x000D_
    margin-left: 5px;_x000D_
}
_x000D_
<div id='box'>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Let's say if you want to set 10px space between the items, you can just set .item {margin-right:10px;} for all, and reset it on the last one .item:last-child {margin-right:0;}

You can also use general sibling ~ or next + sibling selector to set left margin on the items excluding the first one .item ~ .item {margin-left:10px;} or use .item:not(:last-child) {margin-right: 10px;}

Flexbox is so clever that it automatically recalculates and equally distributes the grid.

_x000D_
_x000D_
body {_x000D_
  margin: 0;_x000D_
}_x000D_
_x000D_
.container {_x000D_
  display: flex;_x000D_
}_x000D_
_x000D_
.item {_x000D_
  flex: 1;_x000D_
  background: gray;_x000D_
  height: 50px;_x000D_
}_x000D_
_x000D_
.item:not(:last-child) {_x000D_
  margin-right: 10px;_x000D_
}
_x000D_
<div class="container">_x000D_
  <div class="item"></div>_x000D_
  <div class="item"></div>_x000D_
  <div class="item"></div>_x000D_
  <div class="item"></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

If you want to allow flex wrap, see the following example.

_x000D_
_x000D_
body {_x000D_
  margin: 0;_x000D_
}_x000D_
_x000D_
.container {_x000D_
  display: flex;_x000D_
  flex-wrap: wrap;_x000D_
  margin-left: -10px;_x000D_
}_x000D_
_x000D_
.item {_x000D_
  flex: 0 0 calc(50% - 10px);_x000D_
  background: gray;_x000D_
  height: 50px;_x000D_
  margin: 0 0 10px 10px;_x000D_
}
_x000D_
<div class="container">_x000D_
  <div class="item"></div>_x000D_
  <div class="item"></div>_x000D_
  <div class="item"></div>_x000D_
  <div class="item"></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


There is indeed a nice, tidy, CSS-only way to do this (that one may consider "better").

Of all the answers posted here, I only found one that uses calc() successfully (by Dariusz Sikorski). But when posed with: "but it fails if there are only 2 items in the last row" there was no solution expanded.

This solution addresses the OP's question with an alternative to negative margins and addresses the problem posed to Dariusz.

notes:

  • This example only demonstrates a 3-column layout
  • It uses calc() to let the browser do math the way it wants -- 100%/3 (although 33.3333% should work just as well), and (1em/3)*2 (although .66em should also work well).
  • It uses ::after to pad the last row if there are fewer elements than columns

_x000D_
_x000D_
.flex-container {_x000D_
  display: flex;_x000D_
  justify-content: space-between;_x000D_
  flex-wrap: wrap;_x000D_
}_x000D_
.flex-container:after {_x000D_
  content: "";_x000D_
}_x000D_
.flex-container > div,_x000D_
.flex-container:after {_x000D_
  box-sizing: border-box;_x000D_
  width: calc((100%/3) - ((1em/3)*2));_x000D_
}_x000D_
.flex-container > :nth-child(n + 4) {_x000D_
  margin-top: 1em;_x000D_
}_x000D_
_x000D_
/* the following is just to visualize the items */_x000D_
.flex-container > div,_x000D_
.flex-container:after {_x000D_
  font-size: 2em;_x000D_
}_x000D_
.flex-container {_x000D_
  margin-bottom:4em;_x000D_
}_x000D_
.flex-container > div {_x000D_
  text-align: center;_x000D_
  background-color: #aaa;_x000D_
  padding: 1em;_x000D_
}_x000D_
.flex-container:after {_x000D_
  border: 1px dashed red;_x000D_
}
_x000D_
<h2>Example 1 (2 elements)</h2>_x000D_
<div class="flex-container">_x000D_
  <div>1</div>_x000D_
  <div>2</div>_x000D_
</div>_x000D_
_x000D_
<h2>Example 2 (3 elements)</h2>_x000D_
<div class="flex-container">_x000D_
  <div>1</div>_x000D_
  <div>2</div>_x000D_
  <div>3</div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

Also at https://codepen.io/anon/pen/rqWagE


_x000D_
_x000D_
 :root{_x000D_
  --inner: 20px;_x000D_
  --gap: 10px; /* same as gutter */_x000D_
  _x000D_
  /* flex-flow in row _x000D_
  ---------------------*/_x000D_
  --row-wrap: row wrap;_x000D_
  --row-nowrap: row nowrap;_x000D_
  _x000D_
  /* flex-flow in col _x000D_
  ---------------------*/_x000D_
  --col-wrap: column wrap;_x000D_
  }_x000D_
  _x000D_
  .row {_x000D_
  display: flex;_x000D_
  flex-direction: var(--flex-row);_x000D_
}_x000D_
/* additional wrapping classes (if needed)_x000D_
-------------------------------------------*/_x000D_
.nowrap {_x000D_
  display: flex;_x000D_
  flex-flow: var(--row-nowrap);_x000D_
}_x000D_
.wrap {_x000D_
  display: flex;_x000D_
  flex-flow: var(--col-wrap);_x000D_
}_x000D_
/*----------------------------------------*/_x000D_
[class*="col-"] {_x000D_
  border: 1px solid #ccc;_x000D_
  margin: var(--gap);_x000D_
  padding: var(--inner);_x000D_
  height: auto;_x000D_
  background: #333;_x000D_
  flex: 1 0 auto;_x000D_
}_x000D_
.col-3 {_x000D_
  flex: 3;_x000D_
}
_x000D_
<div class="row">_x000D_
  <div class='col-3'></div>_x000D_
  <div class='col-3'></div>_x000D_
  <div class='col-3'></div>_x000D_
  <div class='col-3'></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

Also you can view this example.


Well, the simplest solution regarding to your CSS, imo, is to add spacers into HTML:

<div id='box'>
  <div class='item'></div>
  <div style='width: 5px;'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

so, you may control it with inline-style or class names.. sometimes, it's also possible to do spacing with padding.

here is the example


tl;dr

$gutter: 8px;

.container {
  display: flex;
  justify-content: space-between;

  .children {
    flex: 0 0 calc(33.3333% - $gutter);
  }
}

With flexbox, creating gutters is a pain, especially when wrapping is involved.

You need to use negative margins (as shown in the question):

#box {
  display: flex;
  width: 100px;
  margin: 0 -5px;
}

... or alter the HTML (as shown in another answer):

<div class='flex-wrapper'>
  <div class='flex'>
    <div class='box'></div>
    <div class='box'></div>
            ...
  </div>
</div>

... or something else.

In any case, you need an ugly hack to make it work because flexbox doesn't provide a "flex-gap" feature (at least for now).

The issue of gutters, however, is simple and easy with CSS Grid Layout.

The Grid spec provides properties that create space between grid items, while ignoring the space between items and the container. These properties are:

  • grid-column-gap
  • grid-row-gap
  • grid-gap (the shorthand for both properties above)

Recently, the spec has been updated to conform with the CSS Box Alignment Module, which provides a set of alignment properties for use across all box models. So the properties are now:

  • column-gap
  • row-gap
  • gap (shorthand)

However, not all Grid-supporting browsers support the newer properties, so I'll use the original versions in the demo below.

Also, if spacing is needed between items and the container, padding on the container works just fine (see the third example in the demo below).

From the spec:

10.1. Gutters: the row-gap, column-gap, and gap properties

The row-gap and column-gap properties (and their gap shorthand), when specified on a grid container, define the gutters between grid rows and grid columns. Their syntax is defined in CSS Box Alignment 3 ยง8 Gaps Between Boxes.

The effect of these properties is as though the affected grid lines acquired thickness: the grid track between two grid lines is the space between the gutters that represent them.

_x000D_
_x000D_
.box {_x000D_
  display: inline-grid;_x000D_
  grid-auto-rows: 50px;_x000D_
  grid-template-columns: repeat(4, 50px);_x000D_
  border: 1px solid black;_x000D_
}_x000D_
_x000D_
.one {_x000D_
  grid-column-gap: 5px;_x000D_
}_x000D_
_x000D_
.two {_x000D_
  grid-column-gap: 10px;_x000D_
  grid-row-gap: 10px;_x000D_
}_x000D_
_x000D_
.three {_x000D_
  grid-gap: 10px;_x000D_
  padding: 10px;_x000D_
}_x000D_
_x000D_
.item {_x000D_
  background: lightgray;_x000D_
}
_x000D_
<div class='box one'>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
</div>_x000D_
_x000D_
<hr>_x000D_
_x000D_
<div class='box two'>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
</div>_x000D_
_x000D_
<hr>_x000D_
_x000D_
<div class='box three'>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

More information:


Simple way of doing this is by adding margin-left and margin-right to the children div and adjust the margin value accordingly

<div class="a">
  <div class="b"></div>
  <div class="b"></div>
  <div class="b"></div>
</div>

css:

.a{
   display: flex;
   justify-content: center;
   background-color: black;
}

.b{
  height: 25px;
  width: 25px;
  background-color: grey;
  margin-left: 5px;
  margin-right: 5px;
}

Using Flexbox in my solution I've used the justify-content property for the parent element (container) and I've specified the margins inside the flex-basis property of the items. Check the code snippet below:

_x000D_
_x000D_
.container {_x000D_
  display: flex;_x000D_
  flex-flow: row wrap;_x000D_
  justify-content: space-around;_x000D_
  margin-bottom: 10px;_x000D_
}_x000D_
_x000D_
.item {_x000D_
  height: 50px;_x000D_
  display: flex;_x000D_
  justify-content: center;_x000D_
  align-items: center;_x000D_
  background-color: #999;_x000D_
}_x000D_
_x000D_
.item-1-4 {_x000D_
  flex-basis: calc(25% - 10px);_x000D_
}_x000D_
_x000D_
.item-1-3 {_x000D_
  flex-basis: calc(33.33333% - 10px);_x000D_
}_x000D_
_x000D_
.item-1-2 {_x000D_
  flex-basis: calc(50% - 10px);_x000D_
}
_x000D_
<div class="container">_x000D_
  <div class="item item-1-4">1</div>_x000D_
  <div class="item item-1-4">2</div>_x000D_
  <div class="item item-1-4">3</div>_x000D_
  <div class="item item-1-4">4</div>_x000D_
</div>_x000D_
<div class="container">_x000D_
  <div class="item item-1-3">1</div>_x000D_
  <div class="item item-1-3">2</div>_x000D_
  <div class="item item-1-3">3</div>_x000D_
</div>_x000D_
<div class="container">_x000D_
  <div class="item item-1-2">1</div>_x000D_
  <div class="item item-1-2">2</div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Here's a grid of card UI elements with spacing completed using flexible box:

enter image description here

I was frustrated with manually spacing the cards by manipulating padding and margins with iffy results. So here's the combinations of CSS attributes I've found very effective:

_x000D_
_x000D_
.card-container {_x000D_
  width: 100%;_x000D_
  height: 900px;_x000D_
  overflow-y: scroll;_x000D_
  max-width: inherit;_x000D_
  background-color: #ffffff;_x000D_
  _x000D_
  /*Here's the relevant flexbox stuff*/_x000D_
  display: flex;_x000D_
  flex-direction: row;_x000D_
  justify-content: center;_x000D_
  align-items: flex-start;_x000D_
  flex-wrap: wrap; _x000D_
}_x000D_
_x000D_
/*Supplementary styles for .card element*/_x000D_
.card {_x000D_
  width: 120px;_x000D_
  height: 120px;_x000D_
  background-color: #ffeb3b;_x000D_
  border-radius: 3px;_x000D_
  margin: 20px 10px 20px 10px;_x000D_
}
_x000D_
<section class="card-container">_x000D_
        <div class="card">_x000D_
_x000D_
        </div>_x000D_
        <div class="card">_x000D_
_x000D_
        </div>_x000D_
        <div class="card">_x000D_
_x000D_
        </div>_x000D_
        <div class="card">_x000D_
_x000D_
        </div>_x000D_
      </section>
_x000D_
_x000D_
_x000D_

Hope this helps folks, present and future.


I have found a solution that is based on the general sibling selector, ~, and allows infinite nesting.

See this code pen for a working example

Basically, inside of column containers, every child that is preceded by another child gets a top margin. Likewise, inside every row container, every child that is preceded by another gets a left margin.

_x000D_
_x000D_
.box {_x000D_
  display: flex;_x000D_
  flex-grow: 1;_x000D_
  flex-shrink: 1;_x000D_
}_x000D_
_x000D_
.box.columns {_x000D_
  flex-direction: row;_x000D_
}_x000D_
_x000D_
.box.columns>.box~.box {_x000D_
  margin-left: 5px;_x000D_
}_x000D_
_x000D_
.box.rows {_x000D_
  flex-direction: column;_x000D_
}_x000D_
_x000D_
.box.rows>.box~.box {_x000D_
  margin-top: 5px;_x000D_
}
_x000D_
<div class="box columns">_x000D_
  <div class="box" style="background-color: red;"></div>_x000D_
  <div class="box rows">_x000D_
    <div class="box rows">_x000D_
      <div class="box" style="background-color: blue;"></div>_x000D_
      <div class="box" style="background-color: orange;"></div>_x000D_
      <div class="box columns">_x000D_
        <div class="box" style="background-color: yellow;"></div>_x000D_
        <div class="box" style="background-color: pink;"></div>_x000D_
      </div>_x000D_
    </div>_x000D_
    <div class="box" style="background-color: green;"></div>_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


You could use the new property gap. I copy paste the explanation I found in this article, as well as more information

CSS grid layout has had gap (previously grid-gap) for some time. By specifying the internal spacing of a containing element rather than the spacing around child elements, gap solves many common layout issues. For example, with gap, you don't have to worry about margins on child elements causing unwanted whitespace around the edges of a containing element:

Unfortunately right now, only FireFox supports gap in flex layouts.

_x000D_
_x000D_
@use postcss-preset-env {_x000D_
  stage: 0;_x000D_
  browsers: last 2 versions_x000D_
}_x000D_
_x000D_
section {_x000D_
  width: 30vw;_x000D_
  _x000D_
  display: grid;_x000D_
  gap: 1rem;_x000D_
  grid-template-columns: repeat(auto-fit, minmax(12ch, 1fr));_x000D_
  _x000D_
  &[flex] {_x000D_
    display: flex;_x000D_
    flex-wrap: wrap;_x000D_
  }_x000D_
  _x000D_
  margin-bottom: 3rem;_x000D_
}_x000D_
_x000D_
.tag {_x000D_
  color: white;_x000D_
  background: hsl(265 100% 47%);_x000D_
  padding: .5rem 1rem;_x000D_
  border-radius: 1rem;_x000D_
}_x000D_
_x000D_
button {_x000D_
  display: inline-flex;_x000D_
  place-items: center;_x000D_
  gap: .5rem;_x000D_
  background: hsl(265 100% 47%);_x000D_
  border: 1px solid hsl(265 100% 67%);_x000D_
  color: white;_x000D_
  padding: 1rem 2rem;_x000D_
  border-radius: 1rem;_x000D_
  font-size: 1.25rem;_x000D_
}_x000D_
_x000D_
body {_x000D_
  min-height: 100vh;_x000D_
  display: flex;_x000D_
  flex-direction: column;_x000D_
  justify-content: center;_x000D_
  align-items: center;_x000D_
}
_x000D_
<section>_x000D_
  <h1>Grid</h1> _x000D_
  <div class="tag">Awesome</div>_x000D_
  <div class="tag">Coo</div>_x000D_
  <div class="tag">Rad</div>_x000D_
  <div class="tag">Math</div>_x000D_
</section>_x000D_
<br>_x000D_
<section flex>_x000D_
  <h1>Flex</h1>_x000D_
  <div class="tag">Awesome</div>_x000D_
  <div class="tag">Coo</div>_x000D_
  <div class="tag">Rad</div>_x000D_
  <div class="tag">Math</div>_x000D_
</section>
_x000D_
_x000D_
_x000D_


You can use transparent borders.

I have contemplated this issue while trying to build a flex grid model which can fallback to a tables + table-cell model for older browsers. And Borders for column gutters seemed to me the best appropriate choice. i.e. Table-cells don't have margins.

e.g.

.column{
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 10px solid transparent;
}

Also note that you need min-width: 50px; for flexbox. The flex model will not handle fixed sizes unless you do flex: none; on the particular child element you want as fixed and therefore excluded from being "flexi". http://jsfiddle.net/GLpUp/4/ But all columns together with flex:none; is no longer a flex model. Here is something closer to a flex model: http://jsfiddle.net/GLpUp/5/

So you can actually use margins normally if you don't need the table-cell fallback for older browsers. http://jsfiddle.net/GLpUp/3/

Setting background-clip: padding-box; will be necessary when using a background, as otherwise the background will flow into the transparent border area.


It won't work in every case but if you have flexible child widths (%) and know the number of items per row you can very cleanly specify the margins of the necessary elements by using nth-child selector/s.

It depends largely on what you mean by "better". This way doesn't require additional wrapper markup for child elements or negative elements - but those things both have their place.

_x000D_
_x000D_
section {_x000D_
  display: block_x000D_
  width: 100vw;_x000D_
}_x000D_
.container {_x000D_
  align-content: flex-start;_x000D_
  align-items: stretch;_x000D_
  background-color: #ccc;_x000D_
  display: flex;_x000D_
  flex-flow: row wrap;_x000D_
  justify-content: flex-start;_x000D_
  width: 100%;_x000D_
}_x000D_
_x000D_
.child-item {_x000D_
  background-color: #c00;_x000D_
  margin-bottom: 2%;_x000D_
  min-height: 5em;_x000D_
  width: 32%;_x000D_
}_x000D_
_x000D_
.child-item:nth-child(3n-1) {_x000D_
  margin-left: 2%;_x000D_
  margin-right: 2%;_x000D_
}
_x000D_
<html>_x000D_
  <body>_x000D_
      <div class="container">_x000D_
        <div class="child-item"></div>_x000D_
        <div class="child-item"></div>_x000D_
        <div class="child-item"></div>_x000D_
        <div class="child-item"></div>_x000D_
        <div class="child-item"></div>_x000D_
        <div class="child-item"></div>_x000D_
        <div class="child-item"></div>_x000D_
      </div>_x000D_
   </body>_x000D_
</html>
_x000D_
_x000D_
_x000D_


According to #ChromeDevSummit there's an implementation of the gap property for Flexbox in Firefox and Chromium-based browsers.

Here's a Live Demo


Assuming:

  • You want 4 column grid layout with wrapping
  • The number of items is not necessarily a multiple of 4

Set a left margin on every item except 1st, 5th, 9th item and so on; and set fixed width on each item. If the left margin is 10px then each row will have 30px margin between 4 items, the percentage width of item can be calculated as follows:

100% / 4 - horizontal-border - horizontal-padding - left-margin * (4 - 1) / 4

This is a decent workaround for issues involving last row of flexbox.

_x000D_
_x000D_
.flex {_x000D_
  display: flex;_x000D_
  flex-direction: row;_x000D_
  flex-wrap: wrap;_x000D_
  margin: 1em 0;_x000D_
  background-color: peachpuff;_x000D_
}_x000D_
_x000D_
.item {_x000D_
  margin-left: 10px;_x000D_
  border: 1px solid;_x000D_
  padding: 10px;_x000D_
  width: calc(100% / 4 - 2px - 20px - 10px * (4 - 1) / 4);_x000D_
  background-color: papayawhip;_x000D_
}_x000D_
_x000D_
.item:nth-child(4n + 1) {_x000D_
  margin-left: 0;_x000D_
}_x000D_
_x000D_
.item:nth-child(n + 5) {_x000D_
  margin-top: 10px;_x000D_
}
_x000D_
<div class="flex">_x000D_
  <div class="item">1</div>_x000D_
  <div class="item">2</div>_x000D_
  <div class="item">3</div>_x000D_
  <div class="item">4</div>_x000D_
</div>_x000D_
<div class="flex">_x000D_
  <div class="item">1</div>_x000D_
  <div class="item">2</div>_x000D_
  <div class="item">3</div>_x000D_
  <div class="item">4</div>_x000D_
  <div class="item">5</div>_x000D_
  <div class="item">6</div>_x000D_
</div>_x000D_
<div class="flex">_x000D_
  <div class="item">1</div>_x000D_
  <div class="item">2</div>_x000D_
  <div class="item">3</div>_x000D_
  <div class="item">4</div>_x000D_
  <div class="item">5</div>_x000D_
  <div class="item">6</div>_x000D_
  <div class="item">7</div>_x000D_
  <div class="item">8</div>_x000D_
  <div class="item">9</div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


CSS gap property:

There is a new gap CSS property for multi-column, flexbox, and grid layouts that works in some browsers now! (See Can I use link 1; link 2). It is shorthand for row-gap and column-gap.

_x000D_
_x000D_
#box {
  display: flex;
  flex-wrap: wrap;
  width: 200px;
  background-color: red;
  gap: 10px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
  border: 1px black solid;
}
_x000D_
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>
_x000D_
_x000D_
_x000D_

As of writing, this works in Firefox, Chrome, and Edge but not Safari.

CSS row-gap property:

The row-gap CSS property for both flexbox and grid layouts allows you to create a gap between rows. I think Safari doesn't support it yet.

#box {
   display: flex;
   row-gap: 10px;
}

CSS column-gap property:

The column-gap CSS property for multi-column, flexbox and grid layouts works allows you to create a gap between columns. I think Safari doesn't support it yet.

#box {
  display: flex;
  column-gap: 10px;
}

Here's my solution, that doesn't require setting any classes on the child elements:

.flex-inline-row {
    display: inline-flex;
    flex-direction: row;
}

.flex-inline-row.flex-spacing-4px > :not(:last-child) {
    margin-right: 4px;
}

Usage:

<div class="flex-inline-row flex-spacing-4px">
  <span>Testing</span>
  <span>123</span>
</div>

The same technique can be used for normal flex rows and columns in addition to the inline example given above, and extended with classes for spacing other than 4px.


#box {
    display:-ms-flex; /* Older IE Compatibility ;) */
    display:flex;
    justify-content:space-between;
}

The 'justify-content' property makes even the gaps, no matter what's your containing div width.

So, lets say your gap is 10px, you have 4 elements so you have 3 gaps: 3*10px = 30px.

#box .item {
    flex-basis:calc((100% - 30px) /4);    
}

This simple calculation just substracts all gaps added up to the container width, the 'justify-content' property above mentioned takes care of the horizontal alignment. Remaining space is divided by 4 (yep that's our number of elements) giving each .item its width. No other property needed, remember they're already aligned!

Hope this helps!

PS: If you need width in your container you set it, same if the gap size or number of elements change, fix the 'flex-basis' calculation in the .item element to address all of them in one line.


I set the spacing on flex items only in the direction stablished by their container. E.g. if a flex container is set to flow from left to right (flex-direction:row) I will only set the right margin on its children, except for the last one:

.flex-lr{
    display:flex;
    flex-direction:row;
}

.flex-lr > *:not(:last-child){
    margin-right:5px;
}

This might seem to work at a first glance but wait! this shouldn't be done when justify-content is set to a value other that start or end, since all other values are already distributing the space on their own.

And what if the items wrap? Then we should add space to the proper cross axis side as well. But, how to know if a container is allowing its children to wrap? And what about wrap-reverse?

All this considerations made me think that this is not a trivial task and it requires a small step beyond.

My approach is based on the build of a brief set of classes that acts as a wrapper of flexbox. This has some benefits:

  1. It allows to "centralize" all vendor prefixes in a single point and forget about that.
  2. It allows to group flexbox properties into a single class, or even rename some of the wording used by flexbox, that sometimes may seem not much intuitive (IMHO).
  3. If I use these classes, I will be able to write other classes based on the flex properties values that they rely on. E.g. I would be able to set the spacing based on the flow direction, the cross axis alignment, wrapping, etc.

I ended up building a flexbox designer to play around with all this, to help understand myself (and others) how flexbox works and to realize how wonderful flexbox is. Plese feel free to use it following the link below:

http://algid.com/Flex-Designer

So, below you will find and abstract of the classes I use and the spacing (margin) utlity for one flow direction. You'll be able to infer the others or find them in the link provided above. Vendor prefixes have been ommited here for brevety.

/* Flex container definition */
.flex-lr{display:flex; flex-direction:row;}
.flex-tb{display:flex; flex-direction:column;}
.flex-rl{display:flex; flex-direction:row-reverse;}
.flex-bt{display:flex; flex-direction:column-reverse;}

/* Wrapping */
.wrap{flex-wrap:wrap;}
.nowrap{flex-wrap:nowrap;}
.wrap-rev{flex-wrap:wrap-reverse;}

/* Main axis alignment */
.align-start{justify-content:flex-start;}
.align-end{justify-content:flex-end;}
.align-center{justify-content:center;}
.align-between{justify-content:space-between;}
.align-around{justify-content:space-around;}
.align-evenly{justify-content:space-evenly;}

/* Cross axis alignment */
.cross-align-start{align-items:flex-start;}
.cross-align-end{align-items:flex-end;}
.cross-align-center{align-items:center;}
.cross-align-stretch{align-items:stretch;}
.cross-align-baseline{align-items:baseline;}

/* Cross axis alignment when content is wrapped */
.wrap-align-start{align-content:flex-start;}
.wrap-align-end{align-content:flex-end;}
.wrap-align-center{align-content:center;}
.wrap-align-stretch{align-content:stretch;}
.wrap-align-between{align-content:space-between;}
.wrap-align-around{align-content:space-around;}

/* Item alignment */
.item-cross-align-start{align-self:flex-start;}
.item-cross-align-end{align-self:flex-end;}
.item-cross-align-center{align-self:center;}
.item-cross-align-stretch{align-self:stretch;}
.item-cross-align-baseline{align-self:baseline;}
.item-cross-align-auto{align-self:auto;}

And now the thing that brought us here: the space between the items:

/* Flow margin (left to right) */
.flex-lr.fm-0 > *:not(:last-child){margin-right:0;}
.flex-lr.fm-1 > *:not(:last-child){margin-right:3px;}
.flex-lr.fm-2 > *:not(:last-child){margin-right:7px;}
.flex-lr.fm-3 > *:not(:last-child){margin-right:15px;}
.flex-lr.fm-4 > *:not(:last-child){margin-right:32px;}

/* Cross axis */
.flex-lr.wrap.fm-0:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap.fm-0.wrap-align-stretch.cross-align-stretch > * {margin-bottom:0;}
.flex-lr.wrap.fm-1:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap.fm-1.wrap-align-stretch.cross-align-stretch > * {margin-bottom:3px;}
.flex-lr.wrap.fm-2:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap.fm-2.wrap-align-stretch.cross-align-stretch > * {margin-bottom:7px;}
.flex-lr.wrap.fm-3:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap.fm-3.wrap-align-stretch.cross-align-stretch > * {margin-bottom:15px;}
.flex-lr.wrap.fm-4:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap.fm-4.wrap-align-stretch.cross-align-stretch > * {margin-bottom:32px;}

/* wrap reverse */
.flex-lr.wrap-rev.fm-0:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap-rev.fm-0.wrap-align-stretch.cross-align-stretch > * {margin-top:0;}
.flex-lr.wrap-rev.fm-1:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap-rev.fm-1.wrap-align-stretch.cross-align-stretch > * {margin-top:3px;}
.flex-lr.wrap-rev.fm-2:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap-rev.fm-2.wrap-align-stretch.cross-align-stretch > * {margin-top:7px;}
.flex-lr.wrap-rev.fm-3:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap-rev.fm-3.wrap-align-stretch.cross-align-stretch > * {margin-top:15px;}
.flex-lr.wrap-rev.fm-4:not(.wrap-align-stretch):not(.wrap-align-between):not(.wrap-align-around) > *, .flex-lr.wrap-rev.fm-4.wrap-align-stretch.cross-align-stretch > * {margin-top:32px;}

Finally, this is how the markup would look like:

<div class="flex-lr cross-align-center fm-3">
    <div>
        Some content here...
    </div>
    <div>
        A bit more stuff here...
    </div>
    <div class="flex-tb fm-3">
        <div>
            Now vertical content
        </div>
        <div>
            etc.
        </div>
    </div>
</div>

This is what I call code out loud.


I have used this for wrapped and fixed width columns. The key here is calc()

SCSS sample

$gap: 10px;

dl {
  display: flex;
  flex-wrap: wrap;
  padding: $gap/2;

  dt, dd {
    margin: $gap/2;}

  dt { // full width, acts as header
    flex: 0 0 calc(100% - #{$gap});}

  dd { // default grid: four columns 
    flex: 0 0 calc(25% - #{$gap});}

  .half { // hall width columns
    flex: 0 0 calc(50% - #{$gap});}

}

Full Codepen sample


I find the easiest way of doing this is with percentages and just allowing the margin to tally up your width

This means you end up with something like this if you where using your example

#box {
   display: flex;
}

.item {
   flex: 1 1 23%;
   margin: 0 1%;
}

Does mean your values are based on the width though which might not be good for everybody.


Why not do it like this:

.item + .item {
    margin-left: 5px;
}

This uses the adjacent sibling selector, to give all .item elements, except the first one a margin-left. Thanks to flexbox, this even results in equally wide elements. This could also be done with vertically positioned elements and margin-top, of course.


Use the css display: inline-flex; value.

html

<div id='box'>
    <div class='item'></div>
    <div class='item'></div>
    <div class='item'></div>
    <div class='item'></div>
</div>

css

.box {
    display: inline-flex;
    gap: 10px; // gap between items
}

I used another approach. Used negative margin on the container, which needs to be the same as each child so for example 10px. Then for each child reduced the width by the total margin each side using calc(), which in this case is 20px.

Here is an example: https://codepen.io/anon/pen/KJLZVg

This helps when doing things responsively as you don't need to target specific nth-child to keep it flush on each side of the container when it wraps.

.parent {
    padding: 0 10px;
}
.container {
    display: flex;
    margin: 0 -10px;
    flex-wrap: wrap;
    width: 100%;
    max-width: 500px;
    margin: 0 auto;
}
.child {
    margin: 0 10px 25px 10px;
    flex: 0 0 calc(25% - 20px);
    height: 40px;
    background: red;
}

<div class="parent">
<div class="container">
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
</div>

Also using flex: 0 0 (width) it helps with IE browser.


_x000D_
_x000D_
#box {_x000D_
  display: flex;_x000D_
  width: 100px;_x000D_
}_x000D_
.item {_x000D_
  background: gray;_x000D_
  width: 50px;_x000D_
  height: 50px;_x000D_
}_x000D_
/* u mean utility */_x000D_
.u-gap-10 > *:not(:last-child) {_x000D_
  margin-right: 10px;_x000D_
}
_x000D_
<div id='box' class="u-gap-10">_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


This solution will work for all cases even if there are multiple rows or any number of elements. But the count of the section should be same you want 4 in first row and 3 is second row it won't work that way the space for the 4th content will be blank the container won't fill.

We are using display: grid; and its properties.

_x000D_
_x000D_
#box {_x000D_
  display: grid;_x000D_
  width: 100px;_x000D_
  grid-gap: 5px;_x000D_
  /* Space between items */_x000D_
  grid-template-columns: 1fr 1fr 1fr 1fr;_x000D_
  /* Decide the number of columns and size */_x000D_
}_x000D_
_x000D_
.item {_x000D_
  background: gray;_x000D_
  width: 100%;_x000D_
  /* width is not necessary only added this to understand that width works as 100% to the grid template allocated space **DEFAULT WIDTH WILL BE 100%** */_x000D_
  height: 50px;_x000D_
}
_x000D_
<div id='box'>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

The Downside of this method is in Mobile Opera Mini will not be supported and in PC this works only after IE10.

Note for complete browser compatability including IE11 please use Autoprefixer


OLD ANSWER

Don't think of it as an old solution, it's still one of the best if you only want single row of elements and it will work with all the browsers.

This method is used by CSS sibling combination, so you can manipulate it many other ways also, but if your combination is wrong it may cause issues also.

.item+.item{
  margin-left: 5px;
}

The below code will do the trick. In this method, there is no need to give margin: 0 -5px; to the #box wrapper.

A working sample for you:

_x000D_
_x000D_
#box {_x000D_
  display: flex;_x000D_
  width: 100px;_x000D_
}_x000D_
.item {_x000D_
  background: gray;_x000D_
  width: 22px;_x000D_
  height: 50px;_x000D_
}_x000D_
.item+.item{_x000D_
 margin-left: 5px;_x000D_
}
_x000D_
<div id='box'>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Flexbox and css calc with multiple rows support

Hello, below is my working solution for all browsers supporting flexbox. No negative margins.

Fiddle Demo

_x000D_
_x000D_
   _x000D_
.flexbox {_x000D_
  display: flex;_x000D_
  flex-direction: row;_x000D_
  flex-wrap: wrap;_x000D_
  justify-content: space-between;_x000D_
}_x000D_
_x000D_
.flexbox > div {_x000D_
  /*_x000D_
    1/3  - 3 columns per row_x000D_
    10px - spacing between columns _x000D_
  */_x000D_
  box-sizing: border-box;_x000D_
  margin: 10px 10px 0 0;_x000D_
  outline: 1px dotted red;_x000D_
  width: calc(1/3*100% - (1 - 1/3)*10px);_x000D_
}_x000D_
_x000D_
/*_x000D_
  align last row columns to the left_x000D_
  3n - 3 columns per row_x000D_
*/_x000D_
.flexbox > div:nth-child(3n) {_x000D_
  margin-right: 0;_x000D_
}_x000D_
_x000D_
.flexbox::after {_x000D_
  content: '';_x000D_
  flex: auto;_x000D_
}_x000D_
_x000D_
/*_x000D_
  remove top margin from first row_x000D_
  -n+3 - 3 columns per row _x000D_
*/_x000D_
.flexbox > div:nth-child(-n+3) {_x000D_
  margin-top: 0;_x000D_
}
_x000D_
<div class="flexbox">_x000D_
  <div>col</div>_x000D_
  <div>col</div>_x000D_
  <div>col</div>_x000D_
  <div>col</div>_x000D_
  <div>col</div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

Take a note this code can be shorter using SASS

Update 2020.II.11 Aligned columns on the last row to the left

Update 2020.II.14 Removed margin-bottom in the last row


Eventually they will add the gap property to flexbox. Until then you could use CSS grid instead which already has the gap property, and just have a single row. Nicer than dealing with margins.


This is not a hack. The same technique is also used by bootstrap and its grid, though, instead of margin, bootstrap uses padding for its cols.

.row {
  margin:0 -15px;
}
.col-xx-xx {
  padding:0 15px;
}

Columnify - A solo class for N columns

Flexbox and SCSS

.columnify {
  display: flex;

  > * {
    flex: 1;

    &:not(:first-child) {
      margin-left: 2rem;
    }
  }
}

Flexbox and CSS

_x000D_
_x000D_
.columnify {_x000D_
  display: flex;_x000D_
}_x000D_
_x000D_
.columnify > * {_x000D_
  flex: 1;_x000D_
}_x000D_
_x000D_
.columnify > *:not(:first-child) {_x000D_
  margin-left: 2rem;_x000D_
}
_x000D_
<div class="columnify">_x000D_
  <div style="display: inline-block; height: 20px; background-color: blue;"></div>_x000D_
  <div style="display: inline-block; height: 20px; background-color: blue"></div>_x000D_
  <div style="display: inline-block; height: 20px; background-color: blue"></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

Play with it on JSFiddle.


Just use .item + .item in selector to match from second .item

_x000D_
_x000D_
#box {_x000D_
  display: inline-flex;_x000D_
  margin: 0 -5px;_x000D_
}_x000D_
.item {_x000D_
  background: gray;_x000D_
  width: 10px;_x000D_
  height: 50px;_x000D_
}_x000D_
_x000D_
#box .item + .item {_x000D_
  margin-left: 10px;_x000D_
}
_x000D_
<div id='box'>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


I posted my flexbox approach here:

One idea I rejected was to remove the padding from the outer columns with something like this:

div:nth-child(#{$col-number}n+1) { padding-left: 0; }
div:nth-child(#{$col-number}n+#{$col-number}) { padding-left: 0; }

But, like other posters here, I prefer the negative margin trick. My fiddle also has responsiveness for anyone is looking for a Sass-based solution. I basically use this approach in place of a grid.

https://jsfiddle.net/x3jvfrg1/


The negative margin trick on the box container works just great. Here is another example working great with order, wrapping and what not.

_x000D_
_x000D_
.container {_x000D_
   border: 1px solid green;_x000D_
   width: 200px;_x000D_
   display: inline-block;_x000D_
}_x000D_
_x000D_
#box {_x000D_
  display: flex;_x000D_
  flex-wrap: wrap-reverse;_x000D_
  margin: -10px;_x000D_
  border: 1px solid red;_x000D_
}_x000D_
.item {_x000D_
  flex: 1 1 auto;_x000D_
  order: 1;_x000D_
  background: gray;_x000D_
  width: 50px;_x000D_
  height: 50px;_x000D_
  margin: 10px;_x000D_
  border: 1px solid blue;_x000D_
}_x000D_
.first {_x000D_
  order: 0;_x000D_
}
_x000D_
<div class=container>_x000D_
<div id='box'>_x000D_
  <div class='item'>1</div>_x000D_
  <div class='item'>2</div>_x000D_
  <div class='item first'>3*</div>_x000D_
  <div class='item'>4</div>_x000D_
  <div class='item'>5</div>_x000D_
</div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


I came across the same issue earlier, then stumbled upon the answer for this. Hope it will help others for future reference.

long answer short, add a border to your child flex-items. then you can specify margins between flex-items to whatever you like. In the snippet, i use black for illustration purposes, you can use 'transparent' if you like.

_x000D_
_x000D_
#box {_x000D_
  display: flex;_x000D_
  width: 100px;_x000D_
  /* margin: 0 -5px; *remove this*/_x000D_
}_x000D_
.item {_x000D_
  background: gray;_x000D_
  width: 50px;_x000D_
  height: 50px;_x000D_
  /* margin: 0 5px; *remove this*/_x000D_
  border: 1px solid black; /* add this */_x000D_
}_x000D_
.item.special{ margin: 0 10px; }
_x000D_
<div id='box'>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item'></div>_x000D_
  <div class='item special'></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


I found a hack because i really need this my self.

_x000D_
_x000D_
/* grid */_x000D_
.container {_x000D_
  display: flex;_x000D_
  flex-flow: row wrap;_x000D_
  justify-content: space-between;_x000D_
}_x000D_
_x000D_
.container::after, /* this makes sure odd element goes left and not space between */_x000D_
.item {_x000D_
  content:"";_x000D_
  width: calc(33.3333% - 20px);_x000D_
  margin-bottom: 40px;_x000D_
}_x000D_
_x000D_
/* extra styling - not important */_x000D_
.item {_x000D_
  height: 100px;_x000D_
  background: #787878;_x000D_
}
_x000D_
<div class="container">_x000D_
  <div class="item"></div>_x000D_
  <div class="item"></div>_x000D_
  <div class="item"></div>_x000D_
  <div class="item"></div>_x000D_
  <div class="item"></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

Here's a post grid with nice flex grow categories also. I think you'd like it. See Codepen