Zebra striping with CSS3

What is it?

Zebra striping is when alternate rows in tabular data are shaded in different colours to make the table easier to read as shown in example below:

To implement this, we need to be able to identify the alternate rows and use our stylesheet to format them differently from the other rows. There are a few different ways that this can be achieved:

  • Add a css class name to alternate rows when generating the HTML server-side
  • Use a plugin for your favourite javascript library (jquery, yui etc)
  • Hand code your own javascript to iterate through each row of the table and add css class to alternate rows

Experimenting with CSS3 recently, I  found the nth-child() pseudo-class selector. This makes it possible to write a style definition that will only apply to every 2nd row (or 3rd, 4th etc as you see fit) instead of applying to every matching row. So with CSS3 we don’t need to mark up our HTML with special class names that only apply to the look and feel and add no semantic meaning to the data. Now we can zebra stripe our tables (or divs, spans etc) using nothing more than CSS, like this:

[code lang="css"]
tbody tr:nth-child(even) {
background-color: #eee;
tbody tr:nth-child(odd) {
background-color: #beb;

Note that the odd and even keywords are shorthand for 2n+1 and 2 respectively (ie. every second element, offset by one element, and every second element).

Is it really that simple?

Well no, it’s never that simple is it? This is a lovely elegant solution for browsers that support CSS3 but it doesn’t help all your IE6, IE7 or even IE8 users because those browsers (and others) don’t support CSS3. So what to do? Well, we could argue that zebra striping is UI frippery which users of older browsers can manage without, so why do anything at all? In time all our users will update to a better browser, right?

Another solution would be revert back to JQuery which has a similar selector but which works in all browsers. In fact JQuery defines odd and even filters which are shortcuts for nth-child(odd) and nth-child(even):

[code lang="javascript"]
$(document).ready(function() {
$('tbody tr:odd').addClass('odd')

Personally, I wouldn’t want to include the Javascript/JQuery method in modern CSS3 browsers where it’s not needed because that would mean downloading extra code over the wire to the browser and performing extra DOM processing on page load. My preference would be a compromise where the above JQuery code is loaded in a Javascript import that is specific to non CSS3 browsers, and then combine the stylesheet definitions for the CSS3 and Javascript techniques into a single entry (so that when you want to change the highlight colour, you only have to make updates in one place), like this:

[code lang="javascript"]
tbody tr.odd, tbody tr:nth-child(even) {
background-color: #eee;

Unfortunately, that doesn’t work because IE will ignore the entire definition if it encounters a selector that it can’t parse. So as far as I can tell, you’re stuck with defining the style twice, once with the CSS3 selector and once with the table row + class name selector. So all this makes me wonder whether it’s worth using the CSS3 selector at all? Going forward, I think I’ll use the CSS3 approach in cases where I don’t have to provide an identical experience for older browsers, otherwise I’ll stick with the tried and tested approach of adding a class name to alternate rows (either server-side where possible, or in Javascript on the browser).

Is there a better approach? If so please let me know in the comments.

One more thing…

I found out about the nth-child() CSS selector by reading The 30 CSS Selectors you Must Memorize. There were several selector types that I wasn’t aware of, and it’s well worth reading and bookmarking.

Leave a Reply