CSS vs Tables: You’re Doing It Wrong

Definitions first.

Table

A specified set of columns and rows with cells that automatically and fairly smartly expand to fit their contents; cells can span rows or columns; the table as a whole can be treated as one block, and cells can contain tables. A table is a metaphor for visually laying out 2-dimensional content.

CSS

cascading style sheets; not floating divs, not any specific markup, but just the concept of the visual display of markup specified by a series of rules that are kept separate from the markup they operate on, generally in an external linked file or a style tag in the head of the document.

Talking Past Each Other

CSS is (for various reasons cited elsewhere ad nauseam), in most cases, the more optimal technological approach. That’s not to say that the existing state of the CSS language is perfect. In fact, even the most vocal CSS advocates regularly assert that there are deep problems with the existing spec and browser support.

Tables are (for various reasons cited elsewhere ad nauseam), in most cases, a more optimal metaphor than any of its rivals. There’s nothing inherently wonderful about the tags themselves. In fact, even the most vocal table advocates regularly assert that the markup is ugly.

Therein lies the crux of the problem. CSS is a great technological approach, and tables are a great metaphor. The question then usually becomes, Should I mark up my content using <div> tags or <table> tags?, which really means, Is the separation of style from content more or less important than using the optimal layout metaphor? The debate goes a little like this:

tables

This layout metaphor is better, so you should use these tags. All you idealists are unrealistic! (Also, if you think markup matters, you believe in fairies. It so doesn’t!)

CSS

Metaphor shmetaphor! You don’t care about the sanctity of data or code quality. Think of the maintenance! (Also, if you can’t do it with divs, you’re stupid. It’s so easy!)

The Right Answer, it would seem, is to use the table metaphor with the CSS technology. In the ideal world, you’d always mark up your content using the tags that would communicate your meaning most clearly to your intended user agents. Then you’d tell user agents how to treat those tags visually. To describe this visual display, you should be able to use the table metaphor, or the float metaphor, or absolute and relative positioning, or anything else, but that should not be done by your markup.

Getting Real

In the real world, it’s not so nice. The CSS specification has a set of display values designed to mimic the table tags, but they aren’t well supported, and anyway, it’s an imperfect imitation of a hack that was not really intended to be used the way we all ended up using it.

In other words, CSS is not an ideal example of what CSS aims at, and the table/tr/td tags are not an ideal implementation of the table/grid metaphor. CSS tables, though they are clever and in some cases quite useful, take it from bad to worse.

The state of the CSS art is not at a point where you can realistically expect to make any significant stylistic changes to your pages without altering the markup. If you need to move the navigation bar from the right to the left, or re-skin the page with dropshadows instead of rounded corners, or convert your gradients from 2-tone to 3-tone, or make your boxes vertically centered instead of top-aligned, you’re probably going to have to change your markup, at least a little.

In theory, it’s possible. I know a handful of my colleagues will vehemently disagree and point at countless approaches to enable virtually any kind of reskinning using only CSS changes. (I’ve used Leslie Sommer’s CSS Mojo technique to great success in the past; we used it for pretty much everything on Yahoo! Buzz.) But let me tell you, from years of experience building production sites with CSS, most of the time, in reality it just doesn’t work that way.

And why should it? What kind of crazy lunatic writes all their HTML by hand in text files, anyhow? Clearly you have some kind of back-end engine spitting it out from templates, so you just change the template, and voilà!, the markup is changed everywhere.

A Very Blue Bike Shed

Working at Yahoo, I’ve met some webdevs with truly incredible CSS ability, who crank out live code under real deadlines to exacting standards. They use CSS, and not tables, and they Get Shit Done. There are a lot of them, more than I can list here, but Nate Koechley, Matt Sweeney, Hedger Wang, and Leslie Sommer all deserve a special mention. I came to Yahoo knowing CSS pretty well, but I became an expert largely as a result of working in such a highly skilled community of developers.

Also due to my time at Yahoo, I’ve seen some absolutely crazy debates about markup and coding standards on the devel-frontend mailing list. I mean, you think this little flare-up in the blogosphere is anything? You got no idea, buddy. Seriously. And these are coworkers who (for the most part) really like and respect one another.

You wanna know a secret? It makes no difference.

Language is as language does. If everyone uses the <table> tag for markup, guess what happens: <table> is now a semantically meaningless (or at least, semantically vague) tag, and any user agents that might care about navigating tabular data have to deal with that fact. It becomes just another <div>, for all intents and purposes, but a little less flexible, and with a default styling that makes it handy for layout.

The passion for the rants comes from the fact that it is meaningless! Of course it’s a fertile ground for bikeshedism!

That’s right: It doesn’t matter.

Use whatever tags work for you. I don’t care. You’ll still be a good person.

I can tell you from experience that a deep knowledge of CSS is essential for serious front-end development. (Most so-called DHTML is actually just manipulating CSS with Javascript, and the Javascript is pretty light.) CSS can do some things that table tags can’t, so you ought to learn it. The reverse is also true, so you should know how to use tables, too.

Write code that you can maintain, that is flexible enough to let you change it without sacrificing the stability of your product. Test it in the user agents that you expect to support. Stop debating the color of this bikeshed.

If there’s ever a good reason to go back and change your tables to divs, or vice versa, you can do that. Hell, plan for that, because whether you use CSS for layout or not, you’re going to need to touch your markup sometimes. It is much much harder to build a product people want than it is to build a product that works in Browser X.

Belorussian translation provided by fatcow