All cells in a <table> element that use the headers attribute must only refer to other cells of that same table
Data table markup can be tedious and confusing. It is important that it is done semantically and with the correct header structure. Screen readers have a number of features to make table navigation easier, but tables must be marked up accurately for these features to work properly.
The Algorithm, in Simple Terms
Why this is Important
Screen readers have a specific way of announcing tables. When tables are not properly marked up, this creates the opportunity for confusing or inaccurate screen reader output.
Sighted users can usually tell at a glance what the table's headers are and what their relationship to the data is. For non-sighted users this must be done in the markup.
When a data table is designed with accessibility in mind, the user enters into table navigation mode, which allows the user to navigate from cell to cell within the table, while hearing the screen reader announce the corresponding table headers for the data cells. Hearing the table headers is especially helpful when navigating through large data tables, or when cells contain similar-sounding data that could be easily confused.
Table navigation mode is not useful, though, if the table lacks accessibility features.
How to Fix the Problem
To fix the problem, ensure that each cell in a table using headers refers to another cell in the same table. This rule checks that references to headers is done right with data cells.
To provide the markup necessary to convey the relationship between header cells and data cells in the data tables, it can be accomplished with the
scope attribute tells the browser and screen reader that everything under the column is related to the header at the top, and everything to the right of the row header is related to that header.
Applying the scope attribute to our table the markup now looks like this:
<table> <caption><strong>Greensprings Running Club Personal Bests</strong></caption> <thead> <tr> <th scope="col">Name</th> <th scope="col">1 mile</th> <th scope="col">5 km</th> <th scope="col">10 km</th> </tr> </thead> <tbody> <tr> <th scope="row">Mary</th> <td>8:32</td> <td>28:04</td> <td>1:01:16</td> </tr> <tr> <th scope="row">Betsy</th> <td>7:43</td> <td>26:47</td> <td>55:38</td> </tr> <tr> <th scope="row">Matt</th> <td>7:55</td> <td>27:29</td> <td>57:04</td> </tr> <tr> <th scope="row">Todd</th> <td>7:01</td> <td>24:21</td> <td>50:35</td> </tr> </tbody> </table>
Note that the top headers for Name, 1 mile, 5 km and 10 km are all marked up with
th elements, as are the row headers for Mary, Betsy, Matt and Todd. Each of these header cell have also been given the
scope attribute values of
row depending on whether they are column or row header cells.
There are two more methods for associating header cells with data cells: colgroup/rowgroup for headers spanning multiple columns or rows, and the
headers method for more complex tables.
- HTML 4