April 23rd in CSS3 by .

Zebra Tables With The CSS3 :nth-child Pseudo Class


One of the ways to make a large amount of tabular data easier to read for the end user is to use alternating row colors. This technique is known as zebra tables and has been around for some time and serves it’s purpose very well.

To accomplish this, developers rely on JavaScript because of the dynamic nature of the tables. If your table was static, you could accomplish this using CSS because you could add a class on every odd row and set the background color for this using CSS. For the most part even this can become very tedious and automating this for all your data tables using JavaScript still remains the chosen solution.

With CSS3 however, we have the option of accomplishing this with two to three lines of CSS and it will work with both static and dynamic tables. What makes this possible is the :nth-child pseudo class. The syntax for :nth-child is as follows:

:nth-child(an+b)

So what is this an+b stuff all about? n Is basically a counter that starts from 0 and incrementally moves up until it runs out of children. b Determines the first element that will be selected and receive the styling we define and lastly a, defines every follow on child that will be selected and styled after out initial starting point. For example:

:nth-child(4n+2)

This will start to apply styling from the second child and then from there every fourth so, in the above case, the children that will be effected will be 2, 6, 10, 14 etc. Besides the calculations, which in themselves are extremely powerful, :nth-child also excepts two named variables, ‘odd’ and ‘even’.

These last two come is really handy when it comes to zebra striped tables. If we for example have the following table:

<table id="stats_tbl">
	<thead>
		<tr>
			<th>Browser</th>
			<th>Audio Tag Support</th>
			<th>Ogg Vorbis</th>
			<th>WAV</th>
			<th>MP3</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>Chrome 10</td>
			<td>Yes</td>
			<td>Yes</td>
			<td>Yes</td>
			<td>Yes</td>
		</tr>
		<tr>
			<td>Opera 10.62</td>
			<td>Yes</td>
			<td>Yes</td>
			<td>Yes</td>
			<td>No</td>
		</tr>
		<tr>
			<td>Opera 11.1</td>
			<td>Yes</td>
			<td>Yes</td>
			<td>Yes</td>
			<td>No</td>
		</tr>
		<tr>
			<td>Firefox 3.6</td>
			<td>Yes</td>
			<td>Yes</td>
			<td>Yes</td>
			<td>No</td>
		</tr>
	</tbody>
</table>

We would apply the following style rule to zebra stripe it:

#stats_tbl tbody tr:nth-child(odd) {
	background-color:#edecec;
}

Launch The Demo

The nth:child pseudo class enjoys pretty wide browser support as shown in the table below:

Browser Is Supported
Chrome Yes
Opera 9.5+ Yes
Safari 3+ Yes
Firefox 3.5+ Yes
Internet Explorer 9 Yes
Internet Explorer 8- No

As you can see versions of Firefox pre 3.5 and our old friends IE8 and below does not support this. But without abandoning the use of this extremely useful selector we can use feature detection to determine whether :nth-child is supported and if not, provide a JavaScript fall back. The following JavaScript function will do the job of determining whether :nth-child is supported:

var nthChildSupported = function() {
	var tbl = $("<table id='nth_child'><tbody><tr><td></td></tr><tr><td></td></tr></tbody></table>")
			  .css({position : "absolute", left : "-9999em"})
			  .appendTo("body"),

	tblStyle = $("<style>#nth_child tr:nth-child(odd) { background-color:#edecec; }</style>")
			  .appendTo("head"),

	backgroundColor = $("#nth_child tbody tr:first")
			  .css("background-color"),

	supported = (backgroundColor === "rgb(237, 236, 236)") || (backgroundColor === "#edecec");					

	$(tbl).remove();
	$(tblStyle).remove();

	return supported;
};

So, to use the ‘native’ CSS and provide a fall back for when it is not supported we can implement this as follows:

if(!nthChildSupported()) {
	alert("no support");
	$("#stats_tbl tbody tr:even td").addClass("odd");
}

NOTE: The above assumes that you have jQuery loaded on your page.

Although jQuery is used by just about everyone but, assuming jQuery is available would be naive so, with that said, below is a script you can make use of if you find yourself in a situation where jQuery is not available to you:

/* Sets the color of each odd row of a table. */
var stripeRows = function(tblId, rowColor) {
	alert("striping");
	var tbl = document.getElementById(tblId),
	tblBody = tbl.getElementsByTagName("tbody"),
	rows = tblBody[0].getElementsByTagName("tr"),
	nmbrOfRows = rows.length;

	for(var i = 0; i < nmbrOfRows; i++) {
		if(odd(i + 1)) {
			var rowCols = rows[i].getElementsByTagName("td"),
			nmbrOfCols = rowCols.length;

			for(var j = 0; j < nmbrOfCols; j++) {
				rowCols[j].style.background = rowColor;
			}
		}
	}
};

if(!nthChildSupported()) {
        stripeRows("stats_tbl", "edecec");
}

Launch The Demo

:nth-child Is a powerful addition to CSS and with a little forethought, can be used effectively today. I look forward to everyone’s comments.

Image Courtesy Atle Brunvoll

Performance Optimization WordPress Plugins by W3 EDGE