15

I am using flexbox to create a nice grid of tiles that automatically wraps when the tiles don't fit on one row.

I use justify-content: space-between so that the tiles stick to the left and right sides of the parent container, and any remaining space is only distributed "in the middle" but not to the left and right.

Any other justify option also puts space to the left and right of the outer two flex items.

The problem is that when a row doesn't have the same number of tiles as the previous row, I'd like the last row's tiles to align to the left. Can this be done using only flex properties?

Current outcome:

▀ ▀ ▀
▀   ▀

Desired outcome:

▀ ▀ ▀
▀ ▀

HTML

<div class="browser">
        <div @click='projectClicked' class="case">
            <h3>Project</h3>
        </div>

        <div @click='projectClicked' class="case">
            <h3>Project</h3>
        </div>

        <div @click='projectClicked' class="case">
            <h3>Project</h3>
        </div>

        <div @click='projectClicked' class="case">
            <h3>Project</h3>
        </div>

        <div @click='projectClicked' class="case">
            <h3>Project</h3>
        </div>
    </div>

CSS

.browser {
    width: 700px;
    display:flex;
    justify-content: space-between;
    padding-bottom:100px;
    flex-wrap:wrap;
    border:1px solid red;
}
.case {
    flex: 0 0 200px;
    background-color:#ccc;
    height:100px;
    border:1px solid blue;
    margin-bottom:10px;
}

Codepen

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Kokodoko
  • 26,167
  • 33
  • 120
  • 197

3 Answers3

8

It's pretty annoying, but you can't use flexbox for that.

The better way is to go with CSS grid instead, and apply

/* for space-around style */
.fixed-grid--around{
  grid-template-columns: repeat(auto-fill, minmax(150px,1fr));
  justify-items: center;
}
/* for space-between style*/
.fixed-grid--between{
  grid-template-columns: repeat(auto-fit, 150px);
  justify-content: space-between;
}
/* both should run fixed width elements equal to the declared in the container */ 
.grid-element{
  width: 150px;
}

By setting the grid columns minimum width to their elements width and the max column width to 1 fr we can get them to evenly distribute the space around them. For space-between style, autofit and space-between does the trick.

So it adds columns to fill the container, evenly distributes the space between them until another column can be added, and wraps as needed. Just what we always hoped for flexbox to do.

A pen I made before exploring the issue:

https://codepen.io/facundocorradini/pen/XVMLEq

If you're gonna use this, make sure to add some fallback for browsers that don't support grid. might be floats, inline-blocks, flex, or whatever. CSS Grid is really good at overriding the fallbacks, so it's fairly easy to apply.

Facundo Corradini
  • 3,825
  • 9
  • 24
5

A solution is to add a hidden element using pseudo-element so you will have 6 elements and keep the layout you need.

.browser {
  width: 700px;
  display: flex;
  justify-content: space-between;
  padding-bottom: 100px;
  flex-wrap: wrap;
  border: 1px solid red;
}

.case {
  flex: 0 0 200px;
  background-color: #ccc;
  height: 100px;
  border: 1px solid blue;
  margin-bottom: 10px;
}
.browser:after {
  content:"";
  flex: 0 0 200px;
}
<div class="browser">
  <div @click='projectClicked' class="case">
    <h3>Project</h3>
  </div>

  <div @click='projectClicked' class="case">
    <h3>Project</h3>
  </div>

  <div @click='projectClicked' class="case">
    <h3>Project</h3>
  </div>

  <div @click='projectClicked' class="case">
    <h3>Project</h3>
  </div>

  <div @click='projectClicked' class="case">
    <h3>Project</h3>
  </div>
</div>
CSS
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
4

You can do this with CSS Grid layout using grid-template-columns: repeat(auto-fit, 200px) andjustify-content: space-between.

.browser {
  width: 700px;
  display: grid;
  grid-template-columns: repeat(auto-fit, 200px);
  justify-content: space-between;
  padding-bottom: 100px;
  border: 1px solid red;
}

.case {
  background-color: #ccc;
  height: 100px;
  border: 1px solid blue;
  margin-bottom: 10px;
}
<div class="browser">
  <div @click='projectClicked' class="case">
    <h3>Project</h3>
  </div>
  <div @click='projectClicked' class="case">
    <h3>Project</h3>
  </div>
  <div @click='projectClicked' class="case">
    <h3>Project</h3>
  </div>
  <div @click='projectClicked' class="case">
    <h3>Project</h3>
  </div>
  <div @click='projectClicked' class="case">
    <h3>Project</h3>
  </div>
</div>
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176