Taking Advantage of What Tables Have to Offer

Posted: April 20, 2009 Comments(17)

We’ll skip right over the nasty past that tables have and cut right to it: tables always have been and will remain very useful in Web design. A well designed group of tabular data can be an outstanding aspect of any document. Unfortunately, tables have a bit of baggage in that applying your desired style can sometimes be quite the challenge. As with everything in Web design, experience will teach you what is easily done and what just isn’t possible.

There is a ton of information available on what you can do with a table, but I’ve got a few things I’d like to share as well.

Effectively structuring your table

Beyond the basic structuring of table data using table rows and table cells, there are a number of elements you can use to make your tabular data that much more structured.

Some of the more basic, but helpful elements to take under your wing are row groups. Row groups consist of thead, tfoot, and tbody. You can group your table heading rows in a thead tag, your table footer rows in tfoot, and the data itself in a tbody tag.

Segmenting your rows into these categories will allow you to write more targeted, straightforward styles for your table. Instead of giving your table rows a specific class, you can use these tags to make your markup more semantic and easier to work with.

As with everything, there are some rules to implementing these tags in your table. For example, the most interesting aspect of this group of tags is that when using tfoot, you must include it before your tbody tag. According to the W3C:

TFOOT must appear before TBODY within a TABLE definition so that user agents can render the foot before receiving all of the (potentially numerous) rows of data

It seems counterintuitive from a human standpoint, but rules are rules.

Perhaps the best kept secret about tables

It wasn’t until a few years ago that I stumbled upon one of the most valuable things I have learned about table markup. By default, columns in tables behave in a liquid manor to accommodate the data held within each cell. If a column of cells has more content, a bigger area will be devoted to that column of data. More often than not, however, when designing a table you’ll want each column of data to have a more targeted width. For a long time, simply due to ignorance, I would solve this issue by giving my table cells a class a defining a width using said classes.

That was of course until I came across column groups. Column groups allow you to tackle this very issue by giving each column a specific id and styling your widths from there. For example:

<table cellpadding="0" cellspacing="0">
	<caption>New York Yankees 2009 Schedule Snippet</caption>
		<col id="date" />
		<col id="time" />
		<col id="opponent" />
		<col id="home_away" />
			<td>April 20</td>
			<td>April 21</td>

To style the columns of the above table:

col#date { width:25%; }
col#time { width:25%; }
col#opponent { width:25%; }
col#home_away { width:25%; }

Using column groups is a much more effective way of styling your columns. There are a number of ways to define the actual width of your columns, you’re not limited to a percentage. Definitely take a few minutes to read the W3C documentation on these elements if you’re not familiar with them, your life may get a bit easier.

Further styling your table

Beyond the markup behind your tables, applying a layer of style is a different aspect of designing your table. There are many techniques for styling your table, and depending on your design, some techniques may work, and others won’t. My general technique involves adding only paint that helps support digesting the data. The last thing you’ll want to go overboard with styling is your tables — they’re meant to be a useful tool used in organizing a group of data. Keep that in mind as you add your style declarations.

One thing I’ll try to do, especially with larger tables, is include a variant of zebra striping. Zebra striping involves alternating every other row of a table to make it easier to discern the relationship between the columns represented in that row. There have been many studies behind the true value of zebra striping, and plenty of articles written. While research shows that zebra striping doesn’t improve readability on any sort of conscious level, in my personal experience, when used properly, zebra striping can make a table easier to read. I will admit, however, that I’m much more likely to use a soft border as a separator between rows as opposed to changing the background color entirely.

Another trick that I’ve become accustomed to using is pseudo-classes, specifically :first-child and :last-child. When applied to table cells, you can easily control your end caps to achieve a more polished look.

For example, using table th:last-child in conjunction with table td:last-child can allow you to right justify both the heading and data cells of your table which may prove beneficial to the overall design.

Share your tips & tricks

That’s what I do to keep my tables in line and looking pretty. Do you have any tricks up your sleeve that you have become comfortable with over time? Do you find yourself working with tables very often from project to project?

Get my newsletter

Receive periodic updates right in the mail!

  • This field is for validation purposes and should be left unchanged.


  1. Column Groups, something I’ve never used but will begin using in the future. The code looks much cleaner without all the class=”blah” on each th or td.

    Thanks for the tip!

  2. Good article, but the example you’ve given doesn’t give the full picture.

    The colgroup property is great for defining collections of columns. In your example, you’ve styled each individual column to 25% but the colgroup element has a span attribute that allows you to achieve the same effect with:

    Or you could just style the col element in CSS to 25%.

  3. Good tip on the colgroups, i saw them long ago when i BUILT sites in tables (gasp), but didn’t remember they existed til now. Not a bad way to go when tabular data is required. Thanks!

  4. I much prefer to use classes in situations like this. That is, classes on the col. This means you can have multiple tables on one page, and not have any conflicts.

    This also means you can have multiple classes for each element and style them accordingly, for width, colour combinations.

    @JR Tashjian: Beware, you can’t do much styling from the col, to influence the TDs as you might expect. So you may still end up classing the TDs on multiple rows, unfortunately.

  5. @Jeff Geerling: colgroup and col are definitely supported by IE6. Unfortunately, however, the enhancements you may add using :first-child and :last-child will not be rendered. It’s not the end of the world though. In my personal practice, I’ll leave IE6 as is (i.e. without right justification on the right-most column) and call it a day. Good browsers get good treats.

    @Phil Wheeler: I’m really anxious to see your comment in its entirety but it looks like a piece got cut off – did you include some HTML for reference? If so, WordPress may have eaten it. I tried to recover it but didn’t find much. If you wouldn’t mind including the sample again that would be great, you’ll just need to wrap your tags in &lt; and &gt; respectively.

    @Jack McDade: You and me both! They definitely remain useful though.

    @Stef Spijkerman: Awesome! Table summaries can be extremely useful for users of assistive technology, and may even help with your SEO a bit if applied correctly in the proper situation.

    @trovster: Yes definitely, I should have indicated in my example that ids were used for the sake of brevity. There have definitely been times where I’ve had multiple tables on a page which benefitted from col classes. Awesome tip, thank you!

  6. NICE! Unlike some of you older guys 😛 I am not well versed in table markup at all. Thanks for the post this is totally enlightening and will definitely save me time in the future.

  7. I heard that CSS selectors or pseudo-classes make HTML rendering slower in all browsers.

  8. COLs with IDs are great thing. The only real problem with them, is that you can’t use col’s ID as selector for it’s children. So, if you have a table with INPUTs in TDs, you can’t write in css something like

    col#first td input { width: 100px; }

  9. This indeed is a standard – aware way of coding the table. The caption tag is interesting 🙂 I have never used in my projects, even if i have read about it 😛 Anyways…looking forward to include those in my future works …
    Nice read JON ! Keep rocking !

  10. I have played around with cols and colgroups before. From what I remember there wasn’t great CSS support. I think I could change the background-color of the columns and that’s about it.

Leave a Reply

Your email address will not be published. Required fields are marked *