The <tbody> Element
As defined in the HTML Living Standard, the <tbody> element represents the body content of a table. It groups the primary data rows, separating them from the header (<thead>) and footer (<tfoot>).
| Product | Price |
|---|---|
| Screen Reader Guide | $25.00 |
| A11y Checklist | $10.00 |
(The data rows are wrapped in a <tbody> element.)
<table>
<thead>...</thead>
<tbody>
<tr>
<td>Data 1</td>
<td>Data 2</td>
</tr>
</tbody>
</table>
View HTML Living Standard: The tbody element
Technical Rules & Hierarchy
- Placement: The
<tbody>must be a child of a<table>. It typically follows the<thead>and precedes the<tfoot>. - Multiple Bodies: Interestingly, a single table can have multiple
<tbody>elements. This is useful for grouping related sets of data within the same table. - Implicit TBody: If you omit the
<tbody>tag but include<tr>elements, the browser will automatically wrap them in an implicit<tbody>in the DOM.
WCAG Requirement: Info and Relationships
Success Criterion 1.3.1 (Level A): Information, structure, and relationships conveyed through presentation can be programmatically determined.
The <tbody> element helps define the "data zone" of the table. For screen reader users, this structural clarity allows them to distinguish between the labels (headers) and the actual values. When multiple <tbody> elements are used, they can be used to create logical sections within a large dataset, making the table easier to navigate.
Best Practices
- Always Explicit: While browsers create an implicit
<tbody>, always write it explicitly in your source code. This improves readability and ensures consistent behavior across different browsers. - Avoid Mixing: Do not place
<th>elements directly inside<tbody>unless they are "row headers" (headers for that specific row). - Styling: Use
<tbody>to apply styles to the entire data section, such as zebra-striping (usingtr:nth-child(even)).
A11y Tip: Row Headers
When the first cell of every row in your <tbody> acts as a label for that row, use <th scope="row"> instead of <td>. This tells the screen reader to announce that specific cell as the header for the rest of the row.