Styling Zebra Striped Tables With CSS

Published November 3, 2008 by saurav.roy.

I recently spent a bit of time on the OneHundredPushups website, and the aspect of the site that most caught my eye (aside from ninja-girl on the front page) was the zebra-striped tables strewn throughout. (For those not in the know, zebra striping tables refers to alternating colored backgrounds on table rows, a la iTunes.) Studies have shown that there is (or at least can be) a slight performance increase associated with zebra striped tables (or at least there isn’t a decrease), and that most users prefer zebra striping to traditional lined tables.

I thought the tables on OneHundredPushups were fairly well done (take a look for yourself here), but a glance at the code showed me that the developer had put more work than was necessary into creating his stripes. Here, I’ll show you an easy way to create a table like the one in the image above (or on the example page here) that doesn’t require you to mess with your XHTML — in fact, you could easily apply this to tables already on your website!

Of course, before we can dive into the CSS, we’ll need a table to style. Mine looks something like this:

<table cellpadding="0" cellspacing="0">
	<tr>
		<th>State</th>
		<th>Date of Poll</th>
		<th>% Voting Dem.</th>
		<th>% Voting GOP</th>
	</tr>
	<tr>
		<td>AR</td>
		<td>10/27</td>
		<td>44</td>
		<td>54</td>
	</tr>
	<tr>
		<td>AZ</td>
		<td>10/23</td>
		<td>41</td>
		<td>49</td>
	</tr>
	... and so on ...
</table>

As you can see, it’s nothing out of the ordinary. I’ve used the old-school cellspacing and cellpadding attributes just to ensure consistent treatment across browsers. And otherwise, I’m using a <th> tag or four to distinguish my table headers from the rest of my code. Otherwise, we’ve just got rows and cells galore. You’ll notice there’s not a single class or ID present here (although if I only wanted to style some of the tables on my site, I’d probably give the styled ones a specific class name).

Next, let’s take a look at the basic CSS styles I’m using:

table {
	width: 100%;
	border: 1px solid #cef;
	text-align: left; }
th {
	font-weight: bold;
	background-color: #acf;
	border-bottom: 1px solid #cef; }
td,th {
	padding: 4px 5px; }

I’ve set the table width to 100% to stop it from collapsing to its minimum size (the default behavior), then given it a pale blue border around the outside. I’ve also set the text alignment throughout the table to “left” — this is to prevent my table headers from centering themselves, which is the default. I prefer my headers to be aligned with my content, but your mileage may vary.

When it comes to the headers, I’ve done a little styling: I’ve given them a background color (a bit darker than my border), bolded the text, and given the bottom of the headings a border what matches the border around my entire table.

Finally, I’m just adding a bit of padding to the interiors of the table cells, to give them a little breathing room. Personally, I think an appropriate use of white (or at least negative) space can be just as critical to legibility as zebra striping — perhaps someone out there more statistically inclined than me should look into that!

Those styles give us our basic table layout, which looks something like this:

So how do we get the alternating rows? For that, I’m creating a new class in my CSS, specifically for the odd (that is, not-even) rows of the table:

.odd {
	background-color: #def; }
.odd td {
	border-bottom: 1px solid #cef; }

This class, once applied to alternating rows of my table, would cause every other row to gain a pale blue background color and a slightly darker bottom border. Since this A List Apart study by Jessica Enders suggested that alternating colored rows and underlines were two of the most aesthetically appealing ways to present tabular data, I figured… why not use both?

Now if I wanted, all I would need to do is go back through my HTML and apply this class to alternating rows in my tables, like the folks at OneHundredPushups have done. However, you’ll notice that my code above doesn’t have any CSS classes. That’s because I prefer to work smarter whenever I have the chance. Instead of turning back to my HTML, I’m going to look to JavaScript (specifically, jQuery) to do my heavy lifting for me.

To apply our class automatically, all the jQuery I need is this:

$(document).ready(function(){
	$("tr:odd").addClass("odd");
});

In layman’s terms, this tiny snippet is saying, “once the document is done loading, cycle through the page, find every ‘odd’ table row, and give it a class of ‘odd.’” Then our CSS takes over and does the rest. Oh, and for the record, you could also write a second rule like this:

$("tr:even").addClass("even");

Which would do the exact same thing as above, only apply it to the “even” rows of the table. And just so you’re not caught off guard by this script’s behavior, it’s good to know in advance that the :odd and :even pseudo-classes start counting at zero, not one. So the first row of your table is, according to jQuery, the “0th” row, and is therefore even.

And there you have it! You can see the whole thing in action here. And now, go forth and make the web a more beautiful (or at least stripy-er) place.

An Argument Against Faux Absolute Positioning

Published June 28, 2008 by saurav.roy.

A week or so ago, Netherlands-based Eric Sol published an article on A List Apart titled “Faux Absolute Positioning,” where he outlines a new system of element positioning that he has developed. Shortly afterwards, a reader wrote to me and asked my opinions on the technique. In the spirit of continuing the fantastic conversations we’ve been having on CSSnewbie recently, I thought I would respond publicly so that others might have the option of offering their opinions as well. But if you haven’t read Eric’s article yet, please do so before responding, so you have the full picture and not just my interpretation of things.

Mr. Sol’s development of the Faux Absolute Positioning technique was born of frustration in trying to use the two dominant positioning techniques: absolute positioning elements, and floating elements. His argument against using absolute positioning for page layout is that it causes any containing elements to collapse (because the element is pulled out of the document flow), which can cause all sorts of problems. This, I will entirely agree with.

However, his argument against using floated elements is that content changes can cause the width of the element to change, which can in turn wreak havoc on float-based layouts. This is partially true. Left to its own devices, for example, a 500 pixel wide column containing a 550 pixel wide image will probably ruin a float-based layout. However, in practice simply applying a rule of “overflow: hidden” to that column would have eliminated any column-resizing problems in nearly all cases, simply cutting off the side of the image when it reached the edge of the column. And considering that using Faux Absolute Positioning relies on an understanding that “the content of the boxes may overlap,” but that “it’s better to risk overlap than risk breaking the whole layout,” I don’t understand what makes using “overflow: hidden” on floated elements so detrimental or different.

But that isn’t my real concern with Eric’s argument for the technique. I’m most concerned with the XHTML structure required to actually implement the technique. As I’ve mentioned before, I’m a bit of a code purist. I believe in using the least amount of code to the greatest effect, and this is especially true when it comes to XHTML. A CSS file can be cached and reused by the browser over an entire website, reducing the strain on a user’s bandwidth. However, each new page a user visits requires them to download an entirely new XHTML page, regardless of how similar that page is to the previous one they visited. In my mind, this is the strongest argument behind switching from presentation-heavy HTML (tables, font tags, etc) to semantic XHTML (and using CSS for presentation) in the first place.

Because of that, I wince when I see the XHTML used to implement the Faux Absolute Positioning technique. Take a look at the sample offered:

<div id="canvas">
  <div class="line">
    <div class="item" id="item1">
      <div class="sap-content">content here</div>
    </div>
  </div>
</div>

Does that structure look strangely familiar? It should – it’s a table, converted into divs. The “canvas” div functions as the table container, while the “line” class of divs acts as rows and the “item” divs behave as table cells. In fact, this technique actually uses an additional div (“sap-content”) inside of each “cell,” bloating the code even further. Compare it to this table-based reimplementation:

<table id="canvas">
  <tr class="line">
    <td class="item" id="item1">
      <div class="sap-content">content here</div>
    </td>
  </tr>
</table>

Now, I understand that there is a semantics argument to be made here. Mr. Sol probably didn’t want to use a table because, semantically speaking, a table should contain tabular data and nothing more. But the problem is, the Faux Absolute Positioning technique simply reimagines tables using divs and classes rather than “tr” and “td” tags.

The real benefit of the technique, Eric states, is that “we can align every item to a predefined position on the grid […] but items still affect the normal flow,” and his insistence on thinking of elements in a page as “cells in [a] grid” is telling: the author really just wants to use a table, but can’t justify it semantically. Thus, he develops a “semantic” alternative that, instead of suffering from non-semantic code, suffers from divitis, classitis, and code bloat instead.

I wrote an article a couple of weeks back on building a calendar using lists instead of tables that ended up sparking a great deal of thoughtful debate of the nature of calendars, the semantic meaning of tables, and the overuse of lists in modern web design. I plan to respond to that debate more fully next week in a separate article, but one point I plan to make then is worth mentioning now: I believe in using semantic code wherever possible, but I also believe in minimizing code wherever possible. One of the (several) reasons I was so intrigued by the possibility of a list-based calendar is that I knew I could create it with less XHTML than a table-based calendar would require, reducing the bandwidth costs of whatever website it was implemented on.

The Faux Absolute Positioning technique, by contrast, requires at least as much XHTML as an equally complex table would require, and may actually require significantly more code because of the additional div inside each “cell.” Depending on the complexity of the site using this technique, we could be talking about 15% greater bandwidth costs on every single page of the website, compared to an identical site using a table for layout. Admittedly, the website could still tout a “table-less” design, at least in the narrowest definition of the phrase. But because of its insistence on rows, columns, and a clearly defined grid, it is at least a table in spirit, and may in fact be more complex and weighty than a table would be in practice. And if a designer is utterly committed to having the rows, columns, and cell-based grid that this technique permits, I would argue that the table tag deserves a second look, if for no other reason that to reduce page size.

At the end of the article, the author does admit that this technique is probably only sufficiently rewarding to be used on rather complex page layouts. But if a site’s layout has reached the level of complexity wherein the only viable options are to use a table to create a grid or reinvent a table to the same end, perhaps it’s the design of the site, and not the code behind the site, that should be reconsidered.

Now, I don’t want to be seen as attacking Mr. Sol’s person or work. I respect the amount of time it must have taken to develop the Faux Absolute Positioning technique and the ingenuity that went into the CSS. My goal here is to simply encourage a debate on the subject. And now that I’ve had my say, I would love to hear what you think about all this.