Data table has missing or incomplete header cell markup
semantic-data-table-headers
- Rule ID:
- semantic-data-table-headers
- User Impact:
- Critical
- WCAG :
- 1.3.1.b
Rule
Data tables must use semantic markup to associate data cells with their corresponding header cell(s).
Background
Tables are static structures that contain one or more rows of data cells. Each data cell is associated with one or more corresponding header cells, which label, or provide context for, the data.
First name | Last name |
---|---|
Jane | Doe |
John | Doe |
The visual arrangement of a table is intended to help users quickly understand the relationship between each data cell and its corresponding headers. Users who rely on assistive technology, however, may not be able to perceive these relationships. Tables must use appropriate semantic markup so assistive technologies can provide users with context for the data they encounter as they navigate throughout the table.
Good Examples
The examples in this section demonstrate how you can properly associate data cells with their corresponding headers in a data table.
All examples represent data from WebAIM's Screen Reader User Survey #9.
Native HTML table elements and attributes
Native HTML <table>
element and attributes are widely supported by assistive technology and should be used whenever possible, especially when the table's data/header relationships are simple.
Screen Reader and Browser | Number of Respondents | Percent of Respondents |
---|---|---|
JAWS with Chrome | 500 | 32.5% |
NVDA with Chrome | 246 | 16.0% |
JAWS with Edge | 194 | 12.6% |
NVDA with Firefox | 149 | 9.7% |
<table>
<thead>
<tr>
<th scope="col">Screen Reader and Browser</th>
<th scope="col">Number of Respondents</th>
<th scope="col">Percent of Respondents</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">JAWS with Chrome</th>
<td>500</td>
<td>32.5%</td>
</tr>
<tr>
<th scope="row">NVDA with Chrome</th>
<td>246</td>
<td>16.0%</td>
</tr>
<tr>
<th scope="row">JAWS with Edge</th>
<td>194</td>
<td>12.6%</td>
</tr>
<tr>
<th scope="row">NVDA with Firefox</th>
<td>149</td>
<td>9.7%</td>
</tr>
</tbody>
</table>
ARIA table
If the table is comprised of <div>
and <span>
elements, you can use the "cell"
role to identify data cells, and the "columnheader"
and "rowheader"
roles to identify headers.
In order for this header-association method to work properly, other table-related roles must also be used on the correct elements.
<div role="table">
<div role="rowgroup">
<div role="row">
<span role="columnheader">Screen Reader and Browser</th>
<span role="columnheader">Number of Respondents</th>
<span role="columnheader">Percent of Respondents</th>
</div>
</div>
<div>
<div role="row">
<span role="rowheader">JAWS with Chrome</th>
<span role="cell">500</td>
<span role="cell">32.5%</td>
</div>
<div role="row">
<span role="rowheader">NVDA with Chrome</th>
<span role="cell">246</td>
<span role="cell">16.0%</td>
</div>
<div role="row">
<span role="rowheader">JAWS with Edge</th>
<span role="cell">194</td>
<span role="cell">12.6%</td>
</div>
<div role="row">
<span role="rowheader">NVDA with Firefox</th>
<span role="cell">149</td>
<span role="cell">9.7%</td>
</div>
</div>
</div>
Using headers/id association
This technique is recommended for complex data tables where column headers change or repeat throughout the table, or where at least some of the data cells are described by three or more headers cells.
First, give each header cell an id
attribute whose value is unique within the entire document. Then, add a headers
attribute to each data cell whose value is a space-separated list of the cell's headers.
In the following code example, the "headers" value for the header cells themselves point to a single empty cell, whose id is "blank". This is not strictly necessary, but can help prevent some assistive technologies from announcing an inappropriate header value when navigating to a header cell.
Technique source: Tables with Multi-Level Headers | Web Accessibility Initiative (WAI) | W3C.
Number of Respondents | Percent of Respondents | |
---|---|---|
Chrome | ||
Jaws | 500 | 32.5% |
NVDA | 246 | 16.0% |
Firefox | ||
NVDA | 149 | 9.7% |
Jaws | 74 | 4.8% |
<table>
<caption>Most common screen reader and browser combinations</caption>
<thead>
<tr>
<th id="blank"></th>
<th id="number" headers="blank">Number of Respondents</th>
<th id="percent" headers="blank">Percent of Respondents</th>
</tr>
</thead>
<tbody>
<tr>
<th id="chrome" headers="blank" colspan="3">Chrome</th>
</tr>
<tr>
<th id="jaws-chrome" headers="blank">Jaws</th>
<td headers="number chrome jaws-chrome">500</td>
<td headers="percent chrome jaws-chrome">32.5%</td>
</tr>
<tr>
<th id="nvda-chrome" headers="blank">NVDA</th>
<td headers="number chrome nvda-chrome">246</td>
<td headers="percent chrome nvda-chrome">16.0%</td>
</tr>
<tr>
<th id="firefox" headers="blank" colspan="3">Firefox</th>
</tr>
<tr>
<th id="nvda-firefox" headers="blank">NVDA</th>
<td headers="number firefox nvda-firefox">149</td>
<td headers="percent firefox nvda-firefox">9.7%</td>
</tr>
<tr>
<th id="jaws-firefox" headers="blank">Jaws</th>
<td headers="number firefox jaws-firefox">74</td>
<td headers="percent firefox jaws-firefox">4.8%</td>
</tr>
</tbody>
</table>