5

When using tables, it is easy to alternate colors in table rows using the nth child selectors (https://stackoverflow.com/a/3084318/1385857). Is there a comparable way to do so when using the flexbox layout. I have the following (from https://philipwalton.github.io/solved-by-flexbox/demos/grids/):

<div class="Grid">
  <div class="Grid-cell"></div>
  [more divs]
  <div class="Grid-cell"></div>
</div>

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

.Grid-cell
{
  flex: 1;
}

Is it possible to alternate row colors in this scenario. To clarify, there are no real rows, only the virtual rows created by flex box due to wrapping.

Community
  • 1
  • 1
Manish
  • 1,726
  • 3
  • 23
  • 29
  • No...there is no CSS what can detect wrapping. you need Javascript....or media queries – Paulie_D Jul 11 '16 at 11:46
  • For alternate rows also you can use the same like `.Grid:nth-child(even)` and `.Grid:nth-child(odd) ` – Mani Jul 11 '16 at 12:11
  • possible duplicate: [Zebra striping a flexbox table with wrapping items](http://stackoverflow.com/q/35355253/3597276) – Michael Benjamin Jul 11 '16 at 13:29
  • I might comment that you should only use classes if the elements cannot be predicted. In your case, _all_ of the inner `div` elements are the same, so you should dispense with the `class` attribute and use the following CSS selector: `.Grid>div`. Over-classing makes your code harder to read and harder to maintain. – Manngo Apr 07 '18 at 00:42
  • For layouts, _everything_ is easier with tables. It's semantically wrong? Yes, but it just works. – rodrigocfd Oct 01 '19 at 13:47

3 Answers3

5

A bit late but it might help others. Here is a working solution I've just come up with. It uses the linear-gradient CSS function.

The only downside is that it requires your cells to have a fixed height.

/* $cell_height: 80px */

.grid {
  display: flex;
  flex-flow: row wrap;

  /* this is where the magic is */
  background-image: linear-gradient(180deg, red 50%, green 50%);
  background-repeat: repeat;
  background-size: 100px 160px; /* width is not relevant, but height must be 2*$cell_height */
}

.grid-cell {
  height: 80px; /* $cell_height */
  
  /* this is just to have a responsive display for the demo */
  width: 25%;
  min-width: 250px;
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}
<div class="grid">
  <div class="grid-cell">1</div>
  <div class="grid-cell">2</div>
  <div class="grid-cell">3</div>
  <div class="grid-cell">4</div>
  <div class="grid-cell">5</div>
  <div class="grid-cell">6</div>
  <div class="grid-cell">7</div>
  <div class="grid-cell">8</div>
  <div class="grid-cell">9</div>
  <div class="grid-cell">10</div>
  <div class="grid-cell">11</div>
  <div class="grid-cell">12</div>
  <div class="grid-cell">13</div>
  <div class="grid-cell">14</div>
</div>
julienc
  • 19,087
  • 17
  • 82
  • 82
  • I like the thinking, it's flexible and responsive. Only downside being height must be specified, in some cases that can be mitigated by variables in css, sass or css-in-js – Xun Yang Dec 21 '22 at 09:44
1

This is a super old post, but I guess still relevant as this issue just came up for me where I had to do a static layout that's responsive going from two columns to four, so trying to organize the columns into rows like an actual table didn't make sense. The above answer with the repeating gradient is creative and works great if you can have a fixed height on your items, but the down-voted nth-child selector answer is better with flex-box if your items need to wrap and have flexible heights. I think that answer just needed to be tweaked a bit for the situation.

    <div class="list-cols">
        <div>One</div>
        <div>Two</div>
        <div>Three</div>
        <div>Four</div>
        <div>Five</div>
        <div>Six</div>
        <div>Seven</div>
        <div>Eight</div>
        <div>Nine</div>
        <div>Ten</div>
        <div>Eleven</div>
        <div>Twelve</div>
        <div>Thirteen</div>
        <div>&nbsp;</div>
        <div>&nbsp;</div>
        <div>&nbsp;</div>
    </div>

Then adjust your selector for how many columns you have. In this case I've got 4 columns, so the nth-of-type formula selects 1-4, 9-12, etc. In your markup, the number of children needs to be divisible by 4 to make a complete last row, so fill it out with empty divs if necessary.

    .list-cols {
        display: flex;
        flex-wrap: wrap;
    }

    .list-cols > div {
        padding: 8px 12px;
        box-sizing: border-box;
        flex-basis: 25%;
        width: 25%;
    }

    .list-cols > div:nth-of-type(8n+1),
    .list-cols > div:nth-of-type(8n+2),
    .list-cols > div:nth-of-type(8n+3),
    .list-cols > div:nth-of-type(8n+4) {
        background: #f2f2f2;
    }
Erik R.
  • 11
  • 1
-3

You can use the same technic with nth-child (2n+1, even, odd), or whatever you want.

The display of the element doesn't interfere with that here.

.Grid {
  display: flex;
  flex-wrap: wrap;
}
.Grid-row {
  flex: 1;
}
.Grid-cell:nth-child(2n+1) {
  background: pink;
}
<div class="Grid">
  <div class="Grid-row">
    <div class="Grid-cell">Grid-cell 1</div>
    <div class="Grid-cell">Grid-cell 2</div>
    <div class="Grid-cell">Grid-cell 3</div>
    <div class="Grid-cell">Grid-cell 4</div>
    <div class="Grid-cell">Grid-cell 5</div>
    <div class="Grid-cell">Grid-cell 6</div>
    <div class="Grid-cell">Grid-cell 7</div>
  </div>
  <div class="Grid-row">
    <div class="Grid-cell">Grid-cell 1</div>
    <div class="Grid-cell">Grid-cell 2</div>
    <div class="Grid-cell">Grid-cell 3</div>
    <div class="Grid-cell">Grid-cell 4</div>
    <div class="Grid-cell">Grid-cell 5</div>
    <div class="Grid-cell">Grid-cell 6</div>
    <div class="Grid-cell">Grid-cell 7</div>
  </div>
</div>
  • 1
    You aren't alternating **rows**, just divs – Paulie_D Jul 11 '16 at 12:34
  • Yes, but if I have well understand the question, @Manish want to create a table, using div and flex box. I edit my first answer example, to give and example visually alterning "row". But maybe I missed something here. – Dry-macarony Jul 11 '16 at 13:52
  • No, he doesn't want to use **actual** rows...that's the point. He wants the *virtual* rows created by the the wrapping to be different colors...and you can't do that with a CSS selector. – Paulie_D Jul 11 '16 at 13:54
  • How. Ok, I see now. Sorry for the misconfusion. – Dry-macarony Jul 11 '16 at 13:56
  • Added a clarification to the question. The goal is to get zebra striping without real rows. – Manish Jul 12 '16 at 03:31