Note: The following applies to data tables, not layout tables. Data is the only semantic use for tables, but if you must use them for layout, the following may not apply.
summary
.The
summary
attribute of thetable
tag should provide a brief description of the data represented in the table.caption
.The
caption
element should be a short title for the table. Use this instead of an heading. Keep in mind that style can be controlled with CSS, so don’t worry about how an element looks, only what it means. More on semantics, later.scope
.Most table header elements (
th
) should contain thescope
attribute with valuescol
for columns androw
for rows.headers
andid
.Complex tables may require the more specific details than the
scope
attribute can provide. In these cases, use theheaders
attribute ontd
elements and correspondingid
attribute on theth
elements.View an example complex table using
headers
andid
. (Example from Jim Thatcher’s 508 Web Tutorial page 9.)Keep in mind that most tables needn’t be this complex. If you find yourself in a position to hand-code an enormous amount of
headers
attributes, consider re-thinking your data structure. With a little bit of skilled information architecture, you may be able to avoid this amount of complexity.thead
,tbody
, andtfoot
.These HTML elements are used to split a data table’s structure into logical divisions: head, body, and foot. Each element is a direct child of the
table
element and should contain one or more table rows (tr
). There are a few practical benefits:Printing a long table that spans multiple pages will automatically print the header and footer in the correct places. This works in any CSS2-compliant browser and Internet Explorer (IE), though IE for Windows requires a small bit of added CSS in order to work properly.
The elements provide another logical, semantic, selector for greater CSS control. For example, you can now distinguish between
th
elements in thethead
or in thetbody
without using a class or id.
The HTML specification for
thead
,tbody
, andtfoot
states thattfoot
should precede the body of the table.<table summary="Feature comparison of Products A and B with price.">
<caption>Product comparison</caption>
<thead>
<tr>
<th scope="col">Feature</th>
<th scope="col">Product A</th>
<th scope="col">Product B</th>
</tr>
</thead>
<tfoot>
<tr>
<th scope="row">Price</th>
<td>$22.95</td>
<td>$28.00</td>
</tr>
</tfoot>
<tbody>
<tr>
<th scope="row">Feature 1</th>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<th scope="row">Feature 2</th>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<th scope="row">Feature 3</th>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<th scope="row">Feature 4</th>
<td>No</td>
<td>Yes</td>
</tr>
</tbody>
</table>
This has the benefit of allowing the footer information to load before the data in an exceptionally large data table, but unfortunately it is not backwards compatible. Browsers that don’t support tbody (such as Netscape 4) will place the
tfoot
before thetbody
information. With the example shown, this is not a significant problem. You’ll have to weigh your compatibility requirements and examine your data to decide where to place thetfoot
. The following example is an acceptable compromise:<table summary="Feature comparison of Products A and B with price.">
<caption>Product comparison</caption>
<thead>
<tr>
<th scope="col">Feature</th>
<th scope="col">Product A</th>
<th scope="col">Product B</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Feature 1</th>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<th scope="row">Feature 2</th>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<th scope="row">Feature 3</th>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<th scope="row">Feature 4</th>
<td>No</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<tfoot>
<tr>
<th scope="row">Price</th>
<td>$22.95</td>
<td>$28.00</td>
</tr>
</tfoot>
For more on data tables, view a list of accessible table resources, compiled by Matthias Gutfeldt, a member of the Web Standards Project.