8

I am looking for the simplest way to zebra stripe the rows on the following responsive flexbox table.

In other words, rows 2 and 4 in this example, but unlimited, I can't know how many rows there will be because this is for a reusable component in a CMS system.

The HTML cannot change but the number of rows and columns will change often. I am happy with setting a limit on columns but not rows.

Is there any way to do it in pure CSS?

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

.Rtable-cell {
  box-sizing: border-box;
  flex: 33.33%;
  margin: -1px 0 0 -1px;
  padding: 5px 10px;
  border: solid 1px slategrey;
}

h3 { margin: 0; }

@media all and (max-width: 500px) {
  .Rtable {
    display: block;
  }
}
<div class="Rtable">

  <div style="order:1;" class="Rtable-cell"><h3>Eddard Stark</h3></div>
  <div style="order:2;" class="Rtable-cell">Has a sword named Ice</div>
  <div style="order:3;" class="Rtable-cell">No direwolf</div>
  <div style="order:4;" class="Rtable-cell">Male</div>
  <div style="order:5;" class="Rtable-cell"><strong>Lord of Winterfell</strong></div>

  <div style="order:1;" class="Rtable-cell"><h3>Jon Snow</h3></div>
  <div style="order:2;" class="Rtable-cell">Has a sword named Longclaw</div>
  <div style="order:3;" class="Rtable-cell">Direwolf: Ghost</div>
  <div style="order:4;" class="Rtable-cell">Male</div>
  <div style="order:5;" class="Rtable-cell"><strong>Knows nothing</strong></div>

  <div style="order:1;" class="Rtable-cell"><h3>Arya Stark</h3></div>
  <div style="order:2;" class="Rtable-cell">Has a sword named Needle</div>
  <div style="order:3;" class="Rtable-cell">Direwolf: Nymeria</div>
  <div style="order:4;" class="Rtable-cell">Female</div>
  <div style="order:5;" class="Rtable-cell"><strong>No one</strong></div>

</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
davidelrizzo
  • 683
  • 8
  • 13
  • Can we clarify: 1. Do you really mean that the number of columns will change? Your data appears to have a pattern. 2. Why can’t you use a table? Contrary to popular belief, tables can be resposive too. 3. You realse that if all the sub-elements have the same class, you can dispense with the class and use a selector such as `.Rtable>div`? – Manngo Apr 07 '18 at 00:48

3 Answers3

1

Ideally, the selector you want would target the even values contained in the style attribute. Something like this:

.Rtable > div[style*="order"][style*={even}] { ... }

Basically, this fantasy selector says: target all divs with a style attribute that contains (*) the values "order" and an even number.

It could be simplified to just:

.Rtable > div[style*={even}] { ... }

But this sort of CSS magic doesn't exist, to my knowledge. (CSS Selectors 3 complete list)

Selectors 4 offers an enhanced :nth-child() pseudo-class, which may be able to accomplish such zebra striping. But this isn't ready for prime time.

For now, I would say the simplest CSS method for accomplishing your goal...

I am looking for the simplest way to zebra stripe rows in the following responsive flexbox table.

... would be to add a class to each element with an even order value.

And with a slight adjustment to your media query, the zebra striping works on different screen sizes.

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

.Rtable-cell {
  box-sizing: border-box;
  flex: 33.33%;
  margin: -1px 0 0 -1px;
  padding: 5px 10px;
  border: solid 1px slategrey;
}

h3 { margin: 0; }

/* NEW */
.stripe { 
  background-color: black;
  color: white;
}

/* ADJUSTED */
@media all and (max-width: 500px) {
  .Rtable {  display: block; }
  .stripe { background-color: white; color: black; }
  .Rtable-cell:nth-child(even) { background-color: black; color: white;}
}
<div class="Rtable">

  <div style="order:1;" class="Rtable-cell"><h3>Eddard Stark</h3></div>
  <div style="order:2;" class="Rtable-cell stripe">Has a sword named Ice</div>
  <div style="order:3;" class="Rtable-cell">No direwolf</div>
  <div style="order:4;" class="Rtable-cell stripe">Male</div>
  <div style="order:5;" class="Rtable-cell"><strong>Lord of Winterfell</strong></div>

  <div style="order:1;" class="Rtable-cell"><h3>Jon Snow</h3></div>
  <div style="order:2;" class="Rtable-cell stripe">Has a sword named Longclaw</div>
  <div style="order:3;" class="Rtable-cell">Direwolf: Ghost</div>
  <div style="order:4;" class="Rtable-cell stripe">Male</div>
  <div style="order:5;" class="Rtable-cell"><strong>Knows nothing</strong></div>

  <div style="order:1;" class="Rtable-cell"><h3>Arya Stark</h3></div>
  <div style="order:2;" class="Rtable-cell stripe">Has a sword named Needle</div>
  <div style="order:3;" class="Rtable-cell">Direwolf: Nymeria</div>
  <div style="order:4;" class="Rtable-cell stripe">Female</div>
  <div style="order:5;" class="Rtable-cell"><strong>No one</strong></div>

</div>

JSFIDDLE DEMO

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • I need the striping to be present at all screen sizes – davidelrizzo Feb 13 '16 at 09:08
  • The striping in my answer *is* present at all screen sizes. – Michael Benjamin Feb 13 '16 at 10:53
  • Oh ok, I see what you did there. Yes manually striping with a class is a possible solution but could get messy if rows are inserted later. I guess you would have to re-apply the striping on every change. – davidelrizzo Feb 14 '16 at 22:46
  • 1
    @davidelrizzo, No need to re-apply striping. And not messy at all. Only the even-numbered `order` values get the stripe. So you could have a rule where every time a `div` gets an even `order` value, it also gets the `.stripe` class. – Michael Benjamin Feb 14 '16 at 23:40
  • Thats a good point. This also works when the table is in horizontal format. I think you have offered the best solution here. Looks like nth-child cannot stripe in patterns as I was looking for. – davidelrizzo Feb 17 '16 at 05:52
  • `nth-child()` counts DOM elements. It doesn't matter what CSS `order` (or even `display:none`) does, `nth-child` cares only about source order. Maybe one day the we'll have `nth-order()` ;-) – Michael Benjamin Mar 12 '16 at 13:23
-1

If I get you right and you mean you want to zebra stripe rows on number 2, 4, ...

for zebra striping row number two you have to change the background color of 2, 5, 7, ... so the answer would be Rtable > div:nth-child(5n + 2) { background-color: #ccc; }. for the 4th row the formula would be nth-child(5n + 4) and so on.

For cases in which you want to repeat the process to unlimited, You have to use a preprocessor like SASS or use JAVASCRIPT. Otherwise the only option in css is to know precisely what rows must be striped.

Farzad Yousefzadeh
  • 2,461
  • 1
  • 20
  • 27
  • You are correct that `nth-child(5n + 2)` will stripe one odd row.. However the CSS needs to set the number of rows in advance and there is no way I can know this for a reusable component. Also it requires a unique line of CSS for every second row. What I am after is a set solution for ANY number of rows. – davidelrizzo Feb 13 '16 at 09:07
  • That could not be done using CSS. Javascript will help. If you are open to a JS solution, I can offer one. – Farzad Yousefzadeh Feb 13 '16 at 11:05
-1

You didn't specify it had to scale for infinite columns, only infinite rows, so you could 4 rules for each column to select every second cell, i.e.:

    /* 4(columns)*2(every second cell) = 8n */
    /* then repeat for each column (+1, +2 etc) */
    .Rtable-cell:nth-child(8n+1) {
        background-color: pink;
    }    
    .Rtable-cell:nth-child(8n+2) {
        background-color: pink;
    }    
    .Rtable-cell:nth-child(8n+3) {
        background-color: pink;
    }    
    .Rtable-cell:nth-child(8n+4) {
        background-color: pink;
    }    

If you're using a preprocessor like LESS, you can make this a mixin:

    /*
    .mxn-TableStripes(@n, @i: 1) when (@i =< @n) {
      @second-row: @n*2;
      @sel: ~"@{second-row}n + @{i}";
      .Rtable-cell:nth-child(@{sel}) {
        background-color: pink;
      }
      .mxn-TableStripes(@n, (@i + 1));
    }
    //Param is number of columns
    .mxn-TableStripes(4);
    */
  • I need to stripe the rows not the columns. This method will not work for rows because I cannot know the number of rows in advance and it could be large. – davidelrizzo Feb 13 '16 at 09:14