table-th-has-data-cells
<th> elements must describe at least one data cell
Checks that a table containing <th> elements also contains at least one <td> data cell for those headers to describe.
Applies to. Applies to <table> elements that keep their table semantics and are included in the accessibility tree, and that contain at least one <th> which is visible, included in the accessibility tree, and not overridden by an explicit role other than rowheader/columnheader. Also applies to the ARIA-only equivalent: an element whose role resolves to grid/treegrid (no native <table> involved) that contains at least one in-scope columnheader/rowheader-role element. Roles are resolved as user agents do: the first token of the role attribute naming a known role, matched in any case; a role attribute with no known token leaves the implicit role in place. In the ARIA-only form, a custom element whose ElementInternals give it the grid, treegrid, header or cell role (this.attachInternals().role), with no role attribute naming another, counts as one with that role attribute does.
Expectation. The table also contains at least one <td> somewhere in it, and, in a table with no colspan or rowspan (or a grid with no aria-colspan, aria-rowspan or aria-colindex), each header cell has a data cell assigned to it by the HTML table model: one after it in its column or row, as its scope allows, with no headers attribute, or one whose headers attribute names it.
What a finding reports.
row,column: where an unassigned header sits, counting from 0: rows from the top, cells from the left within the row.
These data.details fields help to read and reproduce a finding. Apart from reasonCode and the few fields Output schema names as stable, they are not a stable contract: a field may be renamed or dropped in a minor release, so don’t build on them.
Examples
<table><tr><th>Name</th></tr><tr><td>Apple</td></tr></table>
The table has at least one <td> for the <th> to head.
<table><tr><th>Name</th></tr></table>
The table has a <th> but zero <td> anywhere.
How to check
When this rule can’t decide, it reports cantTell and leaves the question to a person. Each question it can ask is listed here under its reason code, with the steps to answer it. A finding carries the same steps as howToCheck, in the scan’s language. See Output schema.
TABLE_TH_NO_ASSIGNED_CELL
- Find the header cell the report names (its row and column are given, counting from 0).
- Look at the cells below it in its column, or after it in its row, as its scope says.
- Decide whether the header is meant to label data: if the cells it should head are missing, or are marked up as headers, it labels nothing.
- If a screen reader is available, move through the table's data cells and note whether this header is ever announced.
Pass. The header is not meant to label data (it can be a plain cell), or the data it heads is marked up so the header is assigned to it.
Fail. A header that should label data has no data cells assigned to it, so its relationship is not conveyed, which fails WCAG 1.3.1.