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
summaryattribute of thetabletag should provide a brief description of the data represented in the table.caption.The
captionelement 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 thescopeattribute with valuescolfor columns androwfor rows.headersandid.Complex tables may require the more specific details than the
scopeattribute can provide. In these cases, use theheadersattribute ontdelements and correspondingidattribute on thethelements.View an example complex table using
headersandid. (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
headersattributes, 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
tableelement 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
thelements in thetheador in thetbodywithout using a class or id.
The HTML specification for
thead,tbody, andtfootstates thattfootshould 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
tfootbefore thetbodyinformation. 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.