50

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

TylerH
  • 20,799
  • 66
  • 75
  • 101
knitevision
  • 3,023
  • 6
  • 29
  • 44
  • Well you still can kinda use the width to control how many items you’ll get per row – via `flex-basis` … – CBroe Jul 24 '15 at 23:43
  • CSS grid would be the thing to solve this in a straight-forward manner today: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout – Jonathan Lin Oct 05 '17 at 13:11

2 Answers2

84

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)

Gareth
  • 133,157
  • 36
  • 148
  • 157
  • 2
    btw margin in pixels works fine with flex. I added ``margin-right: 100px`` and it worked. No overflow like in float layouts. Thanks for the answer, exactly what I needed. Forgout about this property at all – knitevision Jul 25 '15 at 00:01
  • 1
    Once you go for flexbox all out - you will never think about floats which really are a nasty hack. Bootstrap's grid is based on floats. If you have modern browser support, you can use pure flexbox for this way easier and stronger. There is a package called sass-flex-mixins which will shim IE10. – httpete Sep 18 '15 at 13:31
  • @httpete Floats are not a "nasty hack", they work exactly as conceived. On the contrary, the existence of this question helps illustrate what a lousily designed standard flexbox is. – zrooda Feb 01 '17 at 10:02
  • @mystrdat floats are not intended to be used for layout, but floated elements within text. Anyone who has fought bizarrely overlapping elements because of floats has seen this. – httpete Feb 01 '17 at 15:52
  • 1
    So it's a nasty hack or a way to position elements? You're going to have to make a choice. I can see you possibly mean that using floats for layout purposes is not the best choice _today_, which I can agree with in most cases, but there is no bizareness or wonky behavior. – zrooda Feb 02 '17 at 20:09
  • @mystrdat Hmm, I doubt you'd say that the existence of any question about floats (there are [thousands](http://stackoverflow.com/search?q=css+float)) implies what a lousily designed standard it is, so why say the same about flexbox? – Gareth Mar 16 '17 at 16:38
  • Floats were overloaded because people found them useful for more than they were intended to be, while flexbox was supposed to be a layout messiah with direct intent to solve most common stacking problems. I dare to say it ended up not so well designed and failed to solve some common usecases that it could have, like this question. I've made some mixins that change the way flexbox works for a more "photoshop-like" alignment behavior, that's another thing that I just don't understand about flexbox design, it seems like the worse option. http://codepen.io/salsita/full/bgxWBX/ – zrooda Mar 17 '17 at 17:18
  • afaics this answer does not really provide anything in the way of `number: 4;` (it may well be impossible with pure flex) as given in the example code. The number of items per row still depends entirely on the width of the items. If I change their width to a set value and then to other values, I can still cause different counts of items in each row. Maybe I did not understand the question as it was meant to be understood. – Zelphir Kaltstahl May 27 '17 at 16:21
2

I have found a better solution for restricting the number of columns in a row in different devices without using media queries:

HTML:

<div class="flex-container">
    <div class="item">
        <h3>ONE</h3>
        Lorem ipsum dolor sit, amet consectetur adipisicing elit. Cumque maxime odit ipsam, fugit pariatur quis eos
        maiores nostrum? Alias tempora voluptate veritatis omnis quae corporis vero excepturi in rem ipsam.
    </div>
    <div class="item">
        <h3>TWO</h3>
        Lorem ipsum dolor sit, amet consectetur adipisicing elit. Cumque maxime odit ipsam, fugit pariatur quis eos
        maiores nostrum? Alias tempora voluptate veritatis omnis quae corporis vero excepturi in rem ipsam.
    </div>
    <div class="item">
        <h3>THREE</h3>
        Lorem ipsum dolor sit, amet consectetur adipisicing elit. Cumque maxime odit ipsam, fugit pariatur quis eos
        maiores nostrum? Alias tempora voluptate veritatis omnis quae corporis vero excepturi in rem ipsam.
    </div>
    <div class="item">
        <h3>FOUR</h3>
        Lorem ipsum dolor sit, amet consectetur adipisicing elit. Cumque maxime odit ipsam, fugit pariatur quis eos
        maiores nostrum? Alias tempora voluptate veritatis omnis quae corporis vero excepturi in rem ipsam.
    </div>
</div>

CSS:

.flex-container {
        display: flex;
        flex-wrap: wrap;
}
.item {
        box-sizing: border-box;
        flex: 1 0 250px;
        margin: 1rem;
        padding: 1rem;
        border: 1px solid #000;
        border-radius: 5px;
}

Codepen link: https://codepen.io/bala285/pen/YzqpLod

Source: https://www.fourkitchens.com/blog/article/responsive-multi-column-lists-flexbox/

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
  • 3
    Code-only answers are discouraged on Stack Overflow because they don't explain how it solves the problem. Please edit your answer to explain what this code does and how it answers the question, so that it is useful to the OP as well as other users with similar issues. – FluffyKitten Aug 21 '20 at 19:49
  • it has 4 columns. then 2 as you shrink it, then 1. This doesn't accomplish it. – ahnbizcad Sep 03 '20 at 01:25
  • 1
    Not a Code-only answer. @FluffyKitten. The source link has a detailed explanation -- though link answers are frowned upon as well. Everything is frowned upon. Nonetheless an excellent solution -- answer! – grantiago Jul 19 '23 at 18:00
  • @grantiago As you say yourself, having a explanation in the source link doesn't count, and there is a very valid reason for this... *what if the source link breaks or the page is removed or changed*? Then the description is lost too. That's why answers on SO are expected to be self-contained and not rely on other sources. So this *is* a code-only answer as it doesn't include the explanation to make it self-contained. – FluffyKitten Jul 19 '23 at 19:15