Data Tables: Best Practice

More and more people in the Web development business are getting a grasp on how web sites really should be built. Namely with XHTML for structure, CSS for layout and JavaScript for behavior. So tables should be banned from any web page if they do not serve the purpose they were built for: displaying tabular data. In this article I would like to show how the code for displaying such a data table should look like, taking accessibility issues into account. It is inspired by the example that Andy Budd, Cameron Moll and Simon Collison are giving in Chapter 11 of their book, CSS Mastery.

Let’s consider a real-world example for this: Mercer publishes a list of the most expensive cities to live in worldwide. So we take the table that they are using there and turn it into something more accessible and also stylable.

Foundations

First, we start with the basic markup, consisting of table, tr and td and – for the sake of simplicity, with only three data rows.

<table>
    <tr>
        <td>1</td>
        <td>1</td>
        <td>Moscow</td>
        <td>Russia</td>
        <td>134.4</td>
        <td>123.9</td>
    </tr>
    <tr>
        <td>2</td>
        <td>5</td>
        <td>London</td>
        <td>United Kingdom</td>
        <td>126.3</td>
        <td>110.6</td>
    </tr>
    <tr>
        <td>3</td>
        <td>2</td>
        <td>Seoul</td>
        <td>South Korea</td>
        <td>122.4</td>
        <td>121.7</td>
    </tr>
</table>

Nice for a start – but not really pleasing or exciting. If you have a smart code editor that you are working with, maybe ActiveState’s Komodo, it will tell you right away, that this table is missing row/column headers. That is correct, which brings us to our next step.

Adding Column Headers and Structure

Column headers are necessary to tell the user what the data in the respective columns actually represent. For this we will use the thead element. In addition to that, HTML has some elements that let you structure the table into more meaningful segments, which are tbody and tfoot.

<table>
<thead>
    <tr>
        <th colspan="2">Rankings</th>
        <th colspan="2">Location</th>
        <th colspan="2">Cost of Living Index</th>
    </tr>
    <tr>
        <th>March 2007</th>
        <th>March 2006</th>
        <th>City</th>
        <th>Country</th>
        <th>March 2007</th>
        <th>March 2006</th>
    </tr>
</thead>
<tfoot>
    <tr>
        <td colspan="6">Mercer’s survey covers 143 cities across six continents</td>
    </tr>
</tfoot>
<tbody>
    <tr>
        <td>1</td>
        <td>1</td>
        <td>Moscow</td>
        <td>Russia</td>
        <td>134.4</td>
        <td>123.9</td>
    </tr>
    ...
</tbody>
</table>

You can again have a deeper look at the demo page for this step.

Accessibility and Styling Preparation

To make it easier for people using non-visual user agents to know what the data in the table intends to convey, we can use the summary attribute of the table element and the caption element (line wraps marked »):

<table summary="This table displays the results of the »
Cost of Living Survey 2007, ranking cities worldwide.">
<caption>Cost of Living Survey - Worldwide Ranking 2007 (including housing)</caption>
<thead>
...
</tbody>
</table>

The elements colgroup and col let you group together and target columns within your table for styling. Unfortunately, styling those elements is not consistently supported by major browsers like Firefox and IE6/IE7. We will get to that in a second. For now, we would like to group the first two columns together and last two columns together, as they include similar data (digits) to be able to style them later.

<table summary="This table displays the results of the »
Cost of Living Survey 2007, ranking cities worldwide.">
<caption>Cost of Living Survey - Worldwide Ranking 2007 (including housing)</caption>
<colgroup id="rankings" span="2" />  
<colgroup span="2" />
<colgroup id="scores" span="2" />
<thead>
...
</tbody>
</table>

While we are at it, we can use the scope attribute for the th element to tell non-visual user agents for which set of data this element provides header information. We do this as follows:

...
<thead>
    <tr>
        <th scope="colgroup" colspan="2">Rankings</th>
        <th scope="colgroup" colspan="2">Location</th>
        <th scope="colgroup" colspan="2">Cost of Living Index</th>
    </tr>
    <tr>
        <th scope="col">March 2007</th>
        <th scope="col">March 2006</th>
        <th scope="col">City</th>
        <th scope="col">Country</th>
        <th scope="col">March 2007</th>
        <th scope="col">March 2006</th>
    </tr>
</thead>
...

Please check out the demo page for adding accessibility and styling preparation.

Finishing Touches

We now have the markup in place, but the whole thing lacks a bit of styling. To make the table more legible, it is considered good practice to use a different background color on every other table row. To apply this background color, we need to add class=”odd” to the first, third, fifth etc. table row:

<tr class="odd">
    <td>1</td>
    <td>1</td>
    <td>Moscow</td>
    <td>Russia</td>
    <td>134.4</td>
    <td>123.9</td>
</tr>

In addition to that, we want to:

  • Format the caption and the footer
  • Style the headers differently than the rest of the table
  • Add borders to the column groups and the table itself
  • Hovering over a table row should apply different background color and font color to put emphasis on the current row

CSS to the rescue. As stated above, styling columns and column groups is not consistently supported by some major browsers. I found the following CSS issues:

  • IE6/IE7: border CSS property not supported for colgroup and col
  • Firefox: text-align and width not supported for colgroup and col

Please have a look at the final result. Feedback highly appreciated.

Further reading

About the author

This website is the personal web appearance of Klaus Komenda, an Austrian web developer. The about section offers more info about me and this site.

Categories

Copyright © 2000-2014 Klaus Komenda