Grow your CSS skills. Land your dream job.

Filling the Space in the Last Row with Flexbox

Published by Chris Coyier

Chris Albrecht posted a question on StackOverflow about grids. Essentially: imagine you have an element with an unknown number of children. Each of those children is some percentage of the width of parent such that they make equal rows, like 25% wide each for four columns, 33.33% wide each for three columns, etc. The goal is to fill the space of this "grid" evenly. There are an unknown number of children, so let's say you were going with 25% and there were 7 children, that would be 4 in the first row and 3 in the second. Chris needed the final 3 to adjust in width to fill the space, rather than leaving the gap.

Flexbox has just the answer for this, which would otherwise likely need to be a JavaScript intervention.

The solution is essentially making the children able to wrap with flex-wrap, and then filling the space with flex-grow.

.grid {
  display: flex;
  flex-wrap: wrap;
}

.grid-item {
  flex-grow: 1;
  min-width: 25%;
}

Here's a visual example of that when each grid item is red and separated with a border:

By adjusting the min-width at different @media query breakpoints, you can make it responsive pretty easily:

.grid-item {
  flex-grow: 1;
  min-width: 25%;
}
@media (max-width: 1200px) {
  .grid-item {
    min-width: 33.33%; 
  }
}

Here's that demo:

See the Pen Wrapping Flexbox with Media Query Widths by Chris Coyier (@chriscoyier) on CodePen.

If you like to balk at flexbox for not being ready to use yet, this example is for you. flex-wrap wasn't in Firefox at all until pretty recently, and isn't even in stable yet, so probably not a super practical solution for Chris just yet. But remember Firefox auto-updates so when 28 rolls out everyone will have it pretty quickly. I'm still optimistic flexbox will be a pretty standard layout mechanism on new sites within a year or so.

If you only need flexbox for single-directional stuff, falling back to display: table is sometimes an option, if by fallback you mean to replicate the layout with some accuracy. If you need the wrapping, inline-block might work. You can test for flexbox wrapping support with:

@supports not (flex-wrap: wrap) {

}

And possibly fall back to inline-block (with no space between them) If you did that, here's how you might adjust that last row if needed with JavaScript:

var leftovers = $(".child").removeAttr("style").length % 4;
  
if (leftovers > 0) {
  var newWidth = 100 / leftovers;
  var fromHere = $(".child").length - leftovers + 1;
  $(".child:nth-child(n+" + fromHere + ")").css("width", newWidth + "%");
}

Note the hard-coded 4 in there, which assumes 25% children. You could get fancier and detect that. I'll leave that to you. Selecting the last few stragglers (determined by that modulus (%) operator) I did with a bit of an :nth-child recipe. Here's a demo of it though:

See the Pen Wrapping Flexbox with Media Query Widths by Chris Coyier (@chriscoyier) on CodePen.

Remember there is a big ol' guide to all the flexbox properties here.

Comments

  1. Permalink to comment#

    Bookmarks to save the day on every post-IE8 project ever *

  2. Jon
    Permalink to comment#

    Oooooooh… Is there anything flexbox can’t do?

  3. Permalink to comment#

    nice! i was recently looking for something similar – a solution for a balanced flex-wrap navigation with flex auto. the difference to the example above: the width of the containers is not fixed.

  4. Chris Mounsey
    Permalink to comment#

    Oddly, this doesn’t seem to work in Safari 7.0.2, which is annoying.

    CM

    • Chris Mounsey
      Permalink to comment#

      To amplify my slightly terse comment, it seems that Safari simply renders the min-width incorrectly—it just keeps on expanding the parent.

      If you set the min-width to width, then the parent does not expand—the boxes are rendered on one line and just get smaller and smaller.

      I can only get it to work correctly by setting the min-width:25%; to width:25%; and setting all attributes in flex, e.g. flex:1 0 auto;

      CM

  5. Permalink to comment#

    Flexbox is awesome. I’ve used it in my own grid solution and it’s so useful.

    http://grumpywizards.com/Grid/

    Help would be appreciated if anyone wanted to contribute to the open source project! ;-)

  6. thinsoldier
    Permalink to comment#

    This doesn’t solve my problem.

    What I need is a way to have justify-content: space-between on every flex wrapped line except the last line.

    I need the last line to be some kind of combination of space-between & flex-start.

  7. There are also the intrinsic and extrinsic value properties that will hopefully one day help out with this.

    http://caniuse.com/#feat=intrinsic-width

    http://demosthenes.info/blog/662/Design-From-the-Inside-Out-With-CSS-MinContent

  8. Yeah, late to the party. Whatevs.
    Flexbox has the equivalent of “min-width” built into it. Using the shorthand flex property, you could do that all in one declaration:

    flex: 1 0 25%;
    

    Meaning: allow it to grow, don’t allow it to shrink, make the width at least 25%
    It behaves exactly the same way. The new boxes added below will stretch across to fill the space.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".