Search code examples
csshtml-tablezebra-striping

CSS zebra stripe table rows *within* independent table sections?


I'm looking to zebra stripe some tables but these tables are a little different in that they have different sections within each table. The stickler here is I want the zebra striping to be independent for each table section, not just zebra striping over all the rows in the standard way.

I have some prototypes out in some fiddles.

This is what I'm after and is easy to do with javascript, but I'm wondering if this is possible with just css: https://jsfiddle.net/3k79wmjg/4/

Note that the zebra striping "resets" for each table section (the black rows), so it's always:

Black row (table section)
White row (always starts white)
Gray row
White row
Gray row
White row
Gray row

I'm not sure this is even possible with css, the closest I've reached is the following.

These selectors:

tbody tr:not(.section-heading):nth-child(odd) th,
tbody tr:not(.section-heading):nth-child(odd) td {
    background: #f2f2f2;
}

Seen at this fiddle: https://jsfiddle.net/afgeL8mo/

And this selector:

tbody tr:nth-child(even of :not(.section-heading)) {
    background: #f2f2f2;
}

Seen at this fiddle: https://jsfiddle.net/7q25L1vf/

Here is the table html:

<table>
  <caption>Medicare Part A</caption>
  
  <thead>
    <tr>
      <td class="bkg-none"></td>
      <th class="bkg-primary" scope="col">Medicare pays</th>
      <th class="bkg-primary" scope="col">Plan pays</th>
      <th class="bkg-secondary" scope="col">You pay</th>
    </tr>
  </thead>
  
  <tbody>
    <!--start table section-->
    <tr class="section-heading">
      <th id="hospitalization" colspan="4">Hospitalization</th>
    </tr>
    <tr>
      <th scope="row" aria-describedby="hospitalization">First 60 days</th>
      <td>All but $1,600</td>
      <td>$0</td>
      <td>$1,600<br>(Part A deductible)</td>
    </tr>
    <tr>
      <th scope="row" aria-describedby="hospitalization">61st through 90th day</th>
      <td>All but $400 per day</td>
      <td>$400 per day</td>
      <td>$0</td>
    </tr>
    <tr>
      <th scope="row" aria-describedby="hospitalization">91st day and after:<br>While using 60 lifetime reserve days</th>
      <td>All but $800 per day</td>
      <td>$800 per day</td>
      <td>$0</td>
    </tr>
    
    <!--start table section-->
    <tr class="section-heading">
      <th colspan="8">Once lifetime reserve days are used</th>
    </tr>
    <tr>
      <th scope="row">Additional 365 days</th>
      <td>$0</td>
      <td>100% of Medicare eligible expenses</td>
      <td>$0</td>
    </tr>
    <tr>
      <th scope="row">Beyond the additional 365 days</th>
      <td>$0</td>
      <td>$0</td>
      <td>All costs</td>
    </tr>
    
    <!--start table section-->
    <tr class="section-heading">
      <th colspan="8">Skilled nursing facility care</th>
    </tr>
    <tr>
      <th scope="row">First 20 days</th>
      <td>All approved amounts</td>
      <td>$0</td>
      <td>0</td>
    </tr>
    <tr>
      <th scope="row">21st through 100th day</th>
      <td>All but $200 per day</td>
      <td>$0</td>
      <td>Up to $200</td>
    </tr>
    <tr>
      <th scope="row">Lorem ipsum dolor sit amet, consectetur adipiscing elit</th>
      <td>Lorem ipsum dolor</td>
      <td>$0</td>
      <td>$0</td>
    </tr>
    <tr>
      <th scope="row">Lorem ipsum dolor sit amet, consectetur adipiscing elit</th>
      <td>Lorem ipsum dolor</td>
      <td>$0</td>
      <td>$0</td>
    </tr>
    <tr>
      <th scope="row">Lorem ipsum dolor sit amet, consectetur adipiscing elit</th>
      <td>Lorem ipsum dolor</td>
      <td>$0</td>
      <td>$0</td>
    </tr>
    <tr>
      <th scope="row">Lorem ipsum dolor sit amet, consectetur adipiscing elit</th>
      <td>Lorem ipsum dolor</td>
      <td>$0</td>
      <td>$0</td>
    </tr>
    
    <!--more sections and rows-->
    <tr>
      <td colspan="4" style="text-align:left;"><em>more sections/rows...</em></td>
    </tr>
  </tbody>
</table>

And here is the css used out in the fiddles (the selectors referenced above are commented out at the very bottom):

body {
  font-family: sans-serif;
  font-size: 14px;
}

caption {
  text-align: left;
  font-size: 2em;
}

thead th {
  font-weight: bold;
}

thead .bkg-none {
  background: white;
}
thead .bkg-primary {
  background: red;
  color: white;
}
thead .bkg-secondary {
  background: blue;
  color: white;
}

th {
  font-weight: normal;
  text-align: left;
}

th, td {
  padding: 1em;
  text-align: center;
}

tr.section-heading {
  background: black;
}

tr.section-heading th {
  font-weight: bold;
  color: white;
}

tbody tr th:first-of-type {
  text-align: left;
}

.zebra-stripe {
  background: #f2f2f2;
}
/*
tbody tr:not(.section-heading):nth-child(odd) th,
tbody tr:not(.section-heading):nth-child(odd) td {
  background: #f2f2f2;
}
*/
/*
tbody tr:nth-child(even of :not(.section-heading)) {
  background: #f2f2f2;
}
*/

And again, it's all just prototype code.

Anyone have any ideas on if the striping I want to do is possible with just css?

Updated per Riskbreaker's comment, I've updated the table to use multiple elements for each table section. Updated fiddle with desired css zebra striping at https://jsfiddle.net/fpmoxgq9/ for anyone who might come across this.


Solution

  • Per Riskbreaker's comment, I've updated the table to use multiple elements for each table section. Updated fiddle url with desired css zebra striping at bottom of original question.