Spacing between flexbox items

This is what I want:

flex with spacing

The closest I've got. Applying margin on flexbox items, then removing half of it from the first & last children.

The problem is that :first-child is not always the first visually, because I may alter the layout order (example).

Is there a way to take the visual order into account when applying the margin?


The CSS spec has recently been updated to apply gap properties to flexbox elements in addition to CSS grid elements. This feature is supported on the latest versions of all major browsers. With the gap property, you can get what you want with just gap: 10px (or whatever size you want).


You can try setting the same margin for all the boxes, and then revert this on the container:

So replace this:

.flex > * { margin: 0 10px; }    
.flex > :first-child { margin-left: 0; }
.flex > :last-child { margin-right: 0; }

.flex.vertical > :first-child { margin-top: 0; }
.flex.vertical > :last-child { margin-bottom: 0; }

With this:

.flex.vertical { margin: -20px 0 0 -20px; }
.flex > * { margin: 0 0 0 20px; }
.flex.vertical > * { margin: 20px 0 0 0; }

While Rejoy answer works perfectly, it's not responsive-ready, because the rows are locked.

flex-flow is your new friend. However, flex is not without bugs. The negative margin trick we know from various grid framework does work, unless you are on IE, where the elements get wrapped too early because it uses content-box as box-size. But there is an easy workaround.

Working example: https://jsfiddle.net/ys7w1786/

.flex {
  display: flex;  
  flex-direction: row; /* let the content flow to the next row */
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: flex-start;
  margin: -4px -4px; /* grid trick, has to match box margin */
}

The boxes come with flex-basis: auto, because of IE. But we can simply use width instead:

.box {
    flex: 0 0 auto; /* auto is important because of an IE bug with box-size */
    height: 100px;
    display: inline-block;
    background-color: black;
    margin: 4px; /* spacing between boxes, matches parent element */
}

.s1-2{
  width: calc(50% - 8px); 
}
.s1-4{
  width: calc(25% - 8px);
}

here is another way of getting the same thing.

.vertical > div{ margin-bottom: 10px; }
.vertical > div:last-child{ margin-bottom: 0; }
.box + .box{ margin-left: 10px; }