Zebra striping a flexbox table with wrapping items

2019-01-09 08:25发布

问题:

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>

回答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



回答2:

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.



回答3:

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;
    }