How to control number of items per row using media queries in Flexbox?

knitevision picture knitevision · Jul 25, 2015 · Viewed 87k times · Source

So imagine I have the following Markup

<div class="container">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
</div>

And the following styles (SASS)

@mixin max-width($width) {
    @media screen and (max-width: $width) {
        @content;
    }
}

.container {
    display: flex;

    @include max-width(992px) {
        number: 4; //Hypothetical property that is supposed to control number per row
    }

    @include max-width(640px) {
        number: 2; //Hypothetical property that is supposed to control number per row
    }
}
.item {
    background-color: tomato;
    padding: 20px;
    margin-right: 20px;
    flex: 1;
}

Is there a real Flexbox CSS alternative to my hypothetical number property that can control how many items to show per row ?

The float-like grid was handy because you could fit unlimited .items per one .row because of the width. But with flexbox I have to use workarounds like numerous .row classes to control the layout and number of items at different width. I've been lucky so far, but there are certain type of layout which will fail with such an approach.

Codepen link to demonstrate

Answer

Gareth picture Gareth · Jul 25, 2015

I had to get rid of the margin around the blocks, because percentage widths are difficult to cleanly apply to elements with margins, but you can see the changes at http://codepen.io/anon/pen/jPeLYb?editors=110 :

@mixin max-width($width) {
    @media screen and (max-width: $width) {
        @content;
    }
}

.container {
    position: relative;
    display: flex;
    flex-flow: row wrap;
}
.item {
    background-color: tomato;
    box-sizing: border-box;
    padding: 20px;
    outline: 2px solid blue;
    flex: 1;
}

@include max-width(992px) {
    .item {
        flex-basis: 25%;
        background-color: red;
    }
}

@include max-width(640px) {
    .item {
        flex-basis: 50%;
        background-color: green;
    }
}

The important parts here are:

  • flex-flow: row wrap which allows the flexbox to appear on multiple rows (the default is nowrap)

  • flex-basis which is the equivalent of width in this case

  • position: relative which makes the widths relative to the container, rather than the body (this would screw up the rounding)