How to Set Gaps (Gutters) in a Flex Container

Better way to set distance between flexbox items

  • Flexbox doesn't have collapsing margins.
  • Flexbox doesn't have anything akin to border-spacing for tables (edit: CSS property gap fulfills this role in newer browsers, Can I use)

Therefore achieving what you are asking for is a bit more difficult.

In my experience, the "cleanest" way that doesn't use :first-child/:last-child and works without any modification on flex-wrap:wrap is to set padding:5px on the container and margin:5px on the children. That will produce a 10px gap between each child and between each child and their parent.

Demo

.upper {
margin: 30px;
display: flex;
flex-direction: row;
width: 300px;
height: 80px;
border: 1px red solid;

padding: 5px; /* this */
}

.upper > div {
flex: 1 1 auto;
border: 1px red solid;
text-align: center;

margin: 5px; /* and that, will result in a 10px gap */
}

.upper.mc /* multicol test */ {
flex-direction: column;
flex-wrap: wrap;
width: 200px;
height: 200px;
}
<div class="upper">
<div>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa<br/>aaa</div>
<div>aaa<br/>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa</div>
</div>

<div class="upper mc">
<div>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa<br/>aaa</div>
<div>aaa<br/>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa</div>
</div>

Css flexbox gutter with spacing

Your problem is that your divs are 1/3 their parent's width, but then when you add the margin in there, the total width goes over 100%. Unlike padding, which is counted as part of the element's width, margin is in addition to the element's width.

So there's two possible solutions here. The first is to set the width as 1/3 the parent width minus the desired margin. Since you used m-2 in your example, which appears to be .5rem according to Tailwind, we would double that number to account for margins on both the right and left sides of each box, and end up with this:

.flex-wrap > div {  width: calc(33.333333% - 1rem);}
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet"><div class="flex flex-wrap">  <div class="bg-red-500 p-4 m-2">    test  </div>  <div class="bg-red-500 p-4 m-2">    test  </div>  <div class="bg-red-500 p-4 m-2">    test  </div>  <div class="bg-red-500 p-4 m-2">    test  </div>  <div class="bg-red-500 p-4 m-2">    test  </div>  <div class="bg-red-500 p-4 m-2">    test  </div></div>

Creating a flexbox grid with gutters and fixed widths

For various reasons, this job is better suited for CSS Grid than Flexbox.

First, getting the gutters to work in Grid is simple. You can use the grid-gap property, which isn't available yet in flexbox.

Second, the "columns" you're requesting aren't really columns. A column has the same width from top to bottom. You're asking for a masonry layout, which allows content items to span across multiple columns and rows.

Again, this task is much easier to achieve with CSS Grid.

Here's one solution that may work for you (including the media query):

jsFiddle demo

.grid-container {  display: grid;  grid-auto-columns: 1fr;  width: 500px;  grid-auto-rows: 50px;  grid-gap: 10px;}
.col-1 { grid-column: 1 / span 4; grid-row: 1;}
.col-2 { grid-column: 5 / span 6; grid-row: 1;}
.col-3 { grid-column: 1 / span 5; grid-row: 2;}
.col-4 { grid-column: 6 / span 5; grid-row: 2;}
.col-5 { grid-column: 1 / span 6; grid-row: 3;}
.col-6 { grid-column: 7 / span 4; grid-row: 3;}
@media ( max-width: 992px ) { .grid-container>div { grid-column: 1; grid-row: auto; }}
/* non-essential demo styles */
.grid-container { border: 1px solid black; background-color: lightgray;}.grid-container > div { font-size: 1.3em; color: white; display: flex; align-items: center; justify-content: center;}.grid-container > div:nth-child(odd) { background-color: green;}.grid-container > div:nth-child(even) { background-color: orangered;}
<div class="grid-container">  <div class="col-1">40%</div>  <div class="col-2">60%</div>  <div class="col-3">50%</div>  <div class="col-4">50%</div>  <div class="col-5">60%</div>  <div class="col-6">40%</div></div>

CSS flex children gutters with margin

Method # 01:

Add following css on parnet and child respectively (This method will work only when there are only 2 boxes in a row):

/* For Parent Element */
.flex {
justify-content: space-between;
}

/* For Child Element */
.flex-child {
flex: 0 0 calc(50% - 0.5em);
}

* {  box-sizing: border-box;  margin: 0;  padding: 0;}ul {  list-style-type: none;}.flex {  display: -webkit-box;  display: -webkit-flex;  display: -ms-flexbox;  display: flex;  -webkit-flex-wrap: wrap;  -ms-flex-wrap: wrap;  flex-wrap: wrap;}.align-center {  -webkit-box-align: center;  -webkit-align-items: center;  -ms-flex-align: center;  align-items: center;}.space-between {  -webkit-box-pack: justify;  -webkit-justify-content: space-between;  -ms-flex-pack: justify;  justify-content: space-between;}.container {  max-width: 1000px;  margin: 0 auto;  height: 100%;  padding: 0 1em;  border: 1px solid;}nav {  background: #464646;  height: 70px;}.box {  background: lightblue;  padding: 1em;  -webkit-box-flex: 0;  -webkit-flex: 0 0 calc(50% - 0.5em);  -ms-flex: 0 0 calc(50% - 0.5em);  flex: 0 0 calc(50% - 0.5em);  text-align: center;  margin-bottom: 1em;}
<nav>  <div class="container flex align-center space-between">    <ul>      <li>Logo</li>    </ul>    <ul>      <li>Home</li>    </ul>  </div></nav><div class="container">  <header>    <h1>Header</h1>  </header></div><div class="container">  <div class="gallery flex space-between">    <div class="box">BOX 1</div>    <div class="box">BOX 2</div>    <div class="box">BOX 3</div>    <div class="box">BOX 4</div>    <div class="box">BOX 5</div>    <div class="box">BOX 6</div>    <div class="box">BOX 7</div>    <div class="box">BOX 8</div>    <div class="box">BOX 9</div>  </div></div>

Creating a gap using flex

Flex doesn't work that way. If you want a gap in flex, you only have 2 alternative options:

1. Relative Gap

CSS3 offers devs 3 values for justify-content property that help you to align the objects and creating gap between them relatively:

  • space-around: Inserting gaps between its childern and 2 sides of them.
  • space-between: Inserting only gaps between its childern.
  • space-evenly: Similar to space-around but provides equal instead of half-sized space on the edges.
.container {
display: flex;
justify-content: /* put it in here */;
}
  • You cannot fix gaps, so it may break you layout. Especially in the case where your container has loose width or height.

2. Fixed Gap

Using margin property to fix gaps between container's children. Sometime easy, but sometime... it could be quite annoying.

.container {
display: flex;
}

.container > * {
margin: /* top right bottom left | top-bottom right-left | etc. */;
}
  • For complex task, selector nth-child is required.
  • It also requires more calculating.

How can I get `column-gap`'s effect with `display: flex` in Chrome?

Something like this?

.flex-container {  display: flex;  justify-content: space-between;  border: 1px solid black;}.flex-item {  flex-basis: 33%;  height: 30px;  margin-left: 10px;  background-color: #cccccc;  }.flex-item:first-child{  margin-left: 0}
<div class="flex-container">  <div class="flex-item"></div>  <div class="flex-item"></div>  <div class="flex-item"></div></div>

Adding space between flexbox items

There a few things you have to consider.

First of all; with justify-content you define how remaining space is handled. By using space-between your items will be aligned so that the space between them is equal, by setting it to center the remaining space will be around all items, with all items stuck together.

In your case though, there is no remaining space, because your items actually stretch the div. So that doesn't help you.

Next; you've set the width of an item to 50%. Which is fine, your item's will be 50% of the viewport. That's because your grid will implicitly be 100% of the viewport. But because your image overflows the box, you can set margins if you want, and they will put the items further apart, but you need big-ass margins to actually see them. Bigger then the overflowing of your image.

So, to fix this, you make the images responsive by making them as width as the item;

.item img { display: block; height: auto; width: 100%; }

But that poses another problem; flexbox tries to size it's flex items to fit it all into the flex container. So you'll see that it automatically resizes your items so they will all fit in. To fix this, you have to explicitly force the width of your items;

.item { flex: 0 0 50%; }

Which is a shorthand for;

.item { flex-grow: 0; flex-shrink: 0; flex-basis: 50%; }

So basically you say; make my item 50% of it's container, and don't use your awesome algorithm to try to make it bigger or smaller.

Now you've got what you want, and you can use margin-right: 20px for example to create a 20px space between your items.

Full snippet;

.grid { display: flex; width: 100%; }
.item { flex: 0 0 50%; margin-right: 20px; }.item img { display: block; height: auto; width: 100%; }
.article-scroll-mobile { box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); flex-wrap: nowrap; text-align: center; overflow-x: auto; -webkit-overflow-scrolling: touch; /*For iOS smooth scroll effect*/}
<div class="grid article-scroll-mobile">  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div>  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div>  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div>  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div>  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div>  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div></div>

Gaps between items only

To accomplish that, w/o using a script or media query, you will need a minor markup change.

With the extra wrapper you then compensate the left margin set on the items,
so it will only be visible when wrapped.

Note, this trick is well known, since more or less all frameworks, like Bootstrap etc., use this to accomplish the same in their solutions. CSS Grid can do this much simpler, though due to lack of browser support, this is what's mostly used today.

Updated codepen

Stack snippet

body {  margin: 0;  background: black;}
.container { max-width: 700px; margin: 20px auto; overflow: hidden; /* added */}
.wrapper { display: flex; /*flex-direction:row; default, not needed */ flex-wrap: wrap; margin-left: -10px; /* compensate for item margin */}
.wrapper div { min-width: 300px; background: lightblue; border: 1px solid blue; flex-grow: 1; padding: 10px; margin-left: 10px; /* added left margin */}
<div class="container">  <div class="wrapper">    <div>one</div>    <div>two</div>    <div>three</div>    <div>four</div>    <div>five</div>  </div></div>


Related Topics



Leave a reply



Submit