A List Apart

Menu
Issue № 173

Zebra Tables

by Published in CSS, HTML, JavaScript, Graphic Design · 97 Comments

A note from the editors: While useful in its day, the JavaScript and PHP techniques discussed here have been made obsolete (as anticipated by the article itself) by the CSS nth-child pseudo-selectors.

Ever since CSS hit the big time, the table has become increasingly rare. Semantic markup and CSS have replaced tables as layout tools. Tables are now relegated to their original role: displaying data stored in records (rows) and fields (columns).

Article Continues Below

However, their new status doesn’t mean that they still can’t be the targets of a designer’s styles and a developer’s hacks. A table typically presents more information than the rest of the page in a much smaller area, and much effort has been spent in attempting to make tables and other data visualizations as easy to interpret as possible.

The web designer’s and developer’s toolbox of the DOM, CSS, and JavaScript can aid in this effort. This article will take a look at how a simple method of altering a table’s appearance can alter the ease with which its information is interpreted, and along the way, we’ll take a look at how it is possible to mimic some of CSS3’s power through some old-fashioned JavaScript and the DOM.

Zebras and tables and cells, oh my

Take a peek at the following screen-capture (anyone who has used iTunes will instantly recognize its origin):

The stripes, alternating between white and light blue, serve two purposes:

  • They’re aesthetically pleasing.
  • They guide the reader’s eye, allowing the reader to piece together the bits of information that belong to a particular song.

While the latter reason may not be noticable in the above image, take a look at these images to gain an idea of how useful the stripes become when the gap between the two columns is much larger. In the event that you employ a liquid layout for a site, you may end up with the situation shown in the above comparison: columns are separated by large amounts of whitespace, making it difficult to jump from one column to the next. Let’s see if we can’t remedy the problem.

Solution #1: the usual suspect

Re-creating the stripe effect in an XHTML table is pretty easy: we simply alternate background colors for the cells in the even and odd rows. This can be easily achieved by creating two CSS classes (one for even rows, the other for odd) and then binding them to the appropriate rows. A simple example of this method follows:

<html>

<head>

	<title>tables</title>
	
	<style type="text/css">
		#playlist tbody tr.even td {
			background-color: #eee;
		}
		#playlist tbody tr.odd  td {
			background-color: #fff;
		}
	</style>
	
</head>

<body>

	<table id="playlist">
		<tbody>
			<tr class="odd">
				<!-- cells go here -->
			</tr>
			<tr class="even">
				<!-- cells go here -->
			</tr>
			<tr class="odd"> 
				<!-- cells go here -->
			</tr>
			<tr class="even">
				<!-- cells go here -->
			</tr>
		</tbody>
	</table>
	
</body>

</html>

Because there are only two possible holes for this pigeon (even/odd), we can get away with applying only one class, and assume that rows without a class declaration must fall into the the other hole:

<html>

<head>

	<title>tables</title>
	<style type="text/css">
	#playlist tbody tr td {
	background-color: #eee;
	}
	#playlist tbody tr.odd  td {
	background-color: #fff;
	}
	</style>

</head>

<body>

<table id="playlist">
	<tbody>
		<tr class="odd">
			<!-- cells go here -->
		</tr>
		<tr>
			<!-- cells go here -->
		</tr>
		<tr class="odd">
			<!-- cells go here -->
		</tr>
		<tr>
			<!-- cells go here -->
		</tr>
	</tbody>
</table>

</body>

</html>

Pretty simple, no? After compacting the white space in the second example, we’ll have saved our visitors and server even more bytes in precious bandwidth. However, we still run into the same inherent problems as our first example; one may cause you to pull out your hair, while the other is relatively trivial to work around. Let’s take a look-see.

Problem #1: manual labor

The purpose of stylesheets, whether it be on the web via CSS or in an application such as Adobe InDesign is to control the visual properties of elements contained within a document. And while CSS’s selectors allow you to specify which document elements should have which styles applied, the above solution requires the author to apply the appropriate class (either even or odd) to atleast half of the rows in a table. While this isn’t a problem if the table contains only a few rows, copying and pasting gets old very quickly when the table contains tens or hundreds of rows.

This problem can be avoided when the table is generated on the server side, since modifications to the table’s markup require only the editing of a few lines of code. But not every web page is built by a server-side application, and even if you are creating a web app, it is frequently desirable to off-load layout processing to the client through CSS and JavaScript.

Problem #2: row consistency

If you move rows around within the table while authoring the page, chances are that you’ll end up with a sequence of two or more rows with odd or even classes following each other, which will cause your nice stripes to be transformed into a mess of random lines. Correcting the attributes can prove to be tedious when there are many rows in the table.

So what’s a web developer to do? Eventually CSS3’s pseudo-selectors will resolve this problem;  however, browser support for CSS3 is currently sketchy at best.

Solution #2 : open your toolbox

However, there is another solution to our problem. The odd/even method mentioned above uses pure CSS; it’s time to put away the hammer and try the other tools in our belt: JavaScript and the DOM.

Instead of manually binding CSS classes to the appropriate rows, we’ll use a pinch of JavaScript to walk through the table and apply CSS styles. Let’s take a look at the recipe:

  1. Obtain a reference to the table that we want to add stripes to.
  2. With that in hand, drill down into the table’s child elements to find all the <tr>s that are contained within <tbody> elements.
  3. Loop through the <td>s and apply the appropriate styling (which is determined by the location of this <tr> in the table).
  4. Season to taste.

While it sounds pretty simple in theory, it is almost as easy in practice. Honest. The following is our tasty morsel that accomplishes exactly what we need (and scores bonus points for being documented). View the script.

Let’s see how it turned out.

This method comes with two advantages:

  • We can now use classes for more specific uses in the table (using the iTunes metaphor, for example, we can indicate whether the track is enabled or disabled, or if it’s currently selected).
  • We are now able to automatically add stripes to tables in any page that has the stripe() function included; we simply need to invoke the function with the table’s id as an argument at some point in the page.

And while our tasty morsel does require a bit of preparation when compared to our first solution, the code is straightforward and easy to customize. And once it’s in your toolbox, you’ll never have to look at it again.

About the Author

97 Reader Comments

Load Comments