Last week I wrote about my frustrations both with misguided individuals who believe that HTML tables are the result of the Devil’s work and the lack of information available to those web designers who are happy to use tables, but need a little guidance in doing so.This week I introduce the table properly, hopefully enlightening those in the “Devil’s work” camp, and helping those who’d like to know how to use this powerful element correctly.

Web Standards doesn’t mean no tables!

Lets get this out of the way first: Yes tables should not be used for laying out entire web pages. But, nowhere in anything published by the W3C (our guiding light when it comes to the correct use of HTML) are tables banned. In several places they (the W3C) advise that tables should not be used for layout, but never are they ruled out completely. On the contrary, in WCAG 1.0 Guideline 3 it states;

“it is appropriate to use the table element in HTML to mark up tabular information […] using table correctly and creating tables that transform gracefully makes it possible for software to render tables other than as two-dimensional grids.”

So let’s accept that the table is indeed a useful, standards compliant, accessibility friendly and semantically correct tool that all HTML coders should have in their arsenal of markup weaponry. With that agreed let us look at the element and its associates.

The table, table rows and table data

Most web designers will be familiar with these three most basic elements of a table. The <table> tag itself, simply, defines a table. All table rows, data, etc should reside in a table element.

The <tr> tag defines a table row and usually contains a number of data cells (at least).The <td> tag defines a table cell (I believe the D represents “data”). These should appear nested in a tr. Putting these three elements together allows you to devise simple tables of data like below:

    <table>
        <tr>
            <td>10%</td>
            <td>20%</td>
            <td>30%</td>
            <td>40%</td>
        </tr>
        <tr>
            <td>40%</td>
            <td>30%</td>
            <td>20%</td>
            <td>10%</td>
        </tr>
    </table>

Which results in:

10% 20% 30% 40%
40% 30% 20% 10%

Most (if not all) tables of data also need some sort of headings in order to make sense. The <th> (table header) tag is available just for this purpose.

The th tag has to sit inside a tr tag and is used in the same way as the td tag. Its contents are usually displayed in bold (the default in most browsers) but can be controlled via CSS if need be. It should be noted that using th tags just to make something bold is not correct, use CSS or the <strong> element for that.

Adding th tags to our simple table makes it a little easier to understand, increasing its accessibility.

    <table>
        <tr>
            <th>Student</th>
            <th>Result 1</th>
            <th>Result 2</th>
            <th>Result 3</th>
            <th>Result 4</th>
        </tr>
        <tr>
            <td>Mark</td>
            <td>10%</td>
            <td>20%</td>
            <td>30%</td>
            <td>40%</td>
        </tr>
        <tr>
            <td>Sarah</td>
            <td>40%</td>
            <td>30%</td>
            <td>20%</td>
            <td>10%</td>
        </tr>
    </table>

Which results in:

Student Result 1 Result 2 Result 3 Result 4
Mark 10% 20% 30% 40%
Sarah 40% 30% 20% 10%

Head, Foot and Body. In that order

Many tables you will have to deal with, especially if like me you work in the realm of “enterprise applications”, will be much more complex than my simple examples here. In fact they will be much like a good story; having a beginning, middle and end. Or in our case; a head, body and foot.

The <thead>, <tfoot> and <tbody> tags allow you to group sets of table rows into logical collections.

If you use one of these elements, you must also use the other two. They must be used in the order they are written here; thead, tfoot, tbody. This, slightly counterintuitive, ordering allows for something quite special to happen in browsers. If your table has a billion rows a users browser will take some time rendering them. By placing the foot of the table before the body in the mark up the browser is able to render the foot before completely loading all the body rows. On the screen the foot will still appear below the body, but will be rendered along with the table head first, letting the body rows appear like the filling to a data sandwich.For those who use CSS to style up their content, the thead, tfoot and tbody tags offer some convenient hooks onto which styles can be built without having to resort to nasty, bloating, class or id declarations within the tr or td tags.

Adding these elements to our example makes the whole thing more semantically correct, but results in no visual difference in most browsers that I know of.

    <table>
        <thead>
            <tr>
                <th>Student</th>
                <th>Result 1</th>
                <th>Result 2</th>
                <th>Result 3</th>
                <th>Result 4</th>
            </tr>
        </thead>
        <tfoot>
            <td colspan="5">foot</td>
        <tbody>
            <tr>
                <td>Mark</td>
                <td>10%</td>
                <td>20%</td>
                <td>30%</td>
                <td>40%</td>
            </tr>
            <tr>
                <td>Sarah</td>
                <td>40%</td>
                <td>30%</td>
                <td>20%</td>
                <td>10%</td>
            </tr>
        </tbody>
    </table>

Which results in:

Student Result 1 Result 2 Result 3 Result 4
foot        
Mark 10% 20% 30% 40%
Sarah 40% 30% 20% 10%

Captions, colgroups and cols

The <caption> tag should only be used directly after the opening table tag, and there can only be 1 per table. I would only use this element for adding a name or ID that I want the user to see as part of the table. For example in a scientific paper you may have numerous tables of results to display, adding a caption “Table 1: Temperature results*” will help users identify which table any accompanying text refers to.

In most browsers the caption will appear at the top of the table and will be centered. Adding a caption to our example looks like this.

    <table>
        <caption>Student exam results</caption>
        <thead>
            <tr>
                <th>Student</th>
                <th>Result 1</th>
                <th>Result 2</th>
                <th>Result 3</th>
                <th>Result 4</th>
            </tr>
        </thead>
        <tfoot>
            <td colspan="5">foot</td>
        <tbody>
            <tr>
                <td>Mark</td>
                <td>10%</td>
                <td>20%</td>
                <td>30%</td>
                <td>40%</td>
            </tr>
            <tr>
                <td>Sarah</td>
                <td>40%</td>
                <td>30%</td>
                <td>20%</td>
                <td>10%</td>
            </tr>
        </tbody>
    </table>

Which results in:

Student exam results | Student | Result 1 | Result 2 | Result 3 | Result 4 | |—|—|—|—|—| | foot | | Mark | 10% | 20% | 30% | 40% | | Sarah | 40% | 30% | 20% | 10% |

The final two elements that I’ll cover here are two that I have to admit I’ve never used; <colgroup> and <col>. colgroup is described as an element that allows you to group columns for formatting. The col element’s function is to allow you to define attribute values for one or more columns in a table. It must only be used inside a table or colgroup element.

Setting a colgroup element’s “span” attribute allows you to group up the columns that follow, allowing you to apply specific formatting to them. Adding the colgroup element to our example table allows me to specify the width (for example) of the first three columns.

    <table>
        <caption>Student exam results</caption>
        <colgroup span="3" style="width: 50px;"></colgroup>
        <thead>
            <tr>
                <td>Student</td>
                <td>Result 1</td>
                ><td>Result 2</td>
                <td>Result 3</td>
                <td>Result 4</td>
            </tr>
        </thead>
        <tfoot>
            <tr>
                <td colspan="5"> foot</td>
            </tr>
        </tfoot>
        <tbody>
            <tr>
                <td>Mark</td>
                <td>10%</td>
                <td>20%</td>
                <td>30%</td>
                <td>40%</td>
            </tr>
            <tr>
                <td>Sarah</td>
                <td>40%</td>
                <td>30%</td>
                <td>20%</td>
                <td>10%</td>
            </tr>
        </tbody>
    </table>

Which results in:

Student exam results | Student | Result 1 | Result 2 | Result 3 | Result 4 | |—|—|—|—|—| | foot | | Mark | 10% | 20% | 30% | 40% | | Sarah | 40% | 30% | 20% | 10% |

The <col> tag can be used when you want finer control over each column within a colgroup. For example in the table below the col element is used to allow me to format the width of each of the first three columns separately.

    <table>
        <caption>Student exam results</caption>
        <colgroup span="3">
            <col width="20px"></col>
            <col width="40px"></col>
            <col width="50px"></col>
        </colgroup>
        <thead>
            <tr>
                <td>Student</td>
                <td>Result 1</td>
                <td>Result 2</td>
                <td>Result 3</td>
                <td>Result 4</td>
            </tr>
        </thead>
        <tfoot>
            <tr>
                <td colspan="5"> foot</td>
            </tr>
        </tfoot>
        <tbody>
            <tr>
                ><td>Mark</td>
                <td>10%</td>
                <td>20%</td>
                <td>30%</td>
                <td>40%</td>
            </tr>
            <tr>
                <td>Sarah</td>
                <td>40%</td>
                <td>30%</td>
                <td>20%</td>
                <td>10%</td>
            </tr>
        </tbody>
    </table>

Which results in:

Student exam results | Student | Result 1 | Result 2 | Result 3 | Result 4 | |—|—|—|—|—| | foot | | Mark | 10% | 20% | 30% | 40% | | Sarah | 40% | 30% | 20% | 10% |

Summaries, colspans and Non breaking spaces

That’s the lot when it comes to elements available as part of the table. But there are three more things to look at in order to make our tables even better;

  • summaries
  • colspans
  • non breaking spaces.

Summaries

To make the table accessible to non visual browsers the summary attribute of the table element should be set. This summary should describe what the table is showing, without getting into too much detail, enough to allow a user to know whether it’s worth them continuing to delve into the data or not.

Colspan

The colspan attribute can be set for in th or td tags. It allows you to specify that a cell spans a number of columns. Eagle eyed readers will have noticed that I’m using the colspan attribute of the td in the table foot to allow the one cell to span the entire table width.

Non breaking spaces

If for some reason you need to leave a cell empty, for example when you have no data for a particular set of results, to ensure that the table is displayed correctly you should place a &nbsp; character in the cell. Not doing so will cause some browsers (older versions of IE mainly) to break the display of the whole table.

Our example table with a summary and a non breaking space added is below:

    <table summary="Table showing the exam results for a number of third year students">
    <caption>Student exam results</caption>
        <colgroup span="3">
            <col width="20px"></col>
            <col width="40px"></col>
            <col width="50px"></col>
        </colgroup>
        <thead>
            <tr>
                <td>Student</td>
                <td>Result 1</td>
                <td>Result 2</td>
                <td>Result 3</td>
                <td>Result 4</td>
            </tr>
        </thead>
        <tfoot>
            <tr>
                <td colspan="5"> foot</td>
            </tr>
        </tfoot>
        <tbody>
            <tr>
                ><td>Mark</td>
                <td>10%</td>
                <td>20%</td>
                <td>30%</td>
                <td>40%</td>
            </tr>
            <tr>
                <td>Sarah</td>
                <td>40%</td>
                <td>30%</td>
                <td>20%</td>
                <td>10%</td>
            </tr>
        </tbody>
    </table>

Which results in:

Student exam results | Student | Result 1 | Result 2 | Result 3 | Result 4 | |—|—|—|—|—| | foot | | Mark | 10% | 20% | 30% | | | Sarah | 40% | 30% | 20% | 10% |

Conclusion

So there we have it. A whistle stop tour of the most common, and some not so common, tools available as part of the HTML table. Next week I shall talk through some real life examples of how to use everything discussed here in different ways to solve different problems. If you have any specific table related questions or examples you’d like to see walked through let me know via my contact page and I’ll happily work through them.

For further reading about all the elements discussed here also see The W3Schools HTML tables tutorials.