Connect complex table cells to headers with ids
Some tables carry two header rows, or merged cells, or headers running down the middle, and in those the scope attribute runs out of road. H43 is the heavier answer. Give every header cell an id, then list the ids that apply in each data cell's headers attribute, so every value states exactly which headers own it. W3C lists this as sufficient for 1.3.1 Info and Relationships. It is also slow to write, and W3C's own advice is worth taking before you start, which is that several simple tables are usually easier for everybody than one complicated one. The other boundary is layout, and there is a two-line test for it. Take a cell and ask whether its content relates to other content in both its column and its row. If yes, it is a data table. If no, it is a layout table, and none of this markup belongs on it.
How we find it in an audit
Scanners handle the mechanical layer well. A headers attribute pointing at an id that does not exist, or at a cell that is not a header, or two cells sharing an id, all surface automatically. Whether the associations are the right ones is a separate question, so we read cells with a screen reader and check that the headers it announces match the ones a sighted reader would infer from the layout.
How affected users experience it
Move across a complex table with the associations in place and every value arrives with its headers attached. Full-time, 2025, 148. Take them away and you get 148, and the listener has to count rows and columns in their head to work out what it counts. Wrong associations are worse than missing ones, because the table then states something false with complete confidence.
Passes vs. fails
Passes
<th id="ft">Full-time</th>
<th id="y2025">2025</th>
<td headers="ft y2025">148</td>Fails
<tr>
<th>Full-time</th>
<td>148</td>
</tr>
<!-- two header levels apply and the cell claims neither -->How this gets tested
The W3C publishes test rules that define what a checker looks for here.
- ARIA attribute is defined in WAI-ARIAA tool can check this
- ARIA state or property has valid valueA tool can check this
- Element with role attribute has required states and propertiesA tool can check this
- Form field has non-empty accessible nameA tool can check this
- Headers attribute specified on a cell refers to cells in the same table elementA tool can check this
- Role attribute has valid valueA tool can check this
- ARIA global properties not used where prohibitedA tool can check this
- ARIA required context roleA tool can check this
- ARIA required owned elementsA tool can check this
- ARIA state or property is permittedA tool can check this
- Table header cell has assigned cellsA tool can check this
Other ways to satisfy this rule
52 guides on this site are filed under 1.3.1 Info and Relationships. W3C lists this one as sufficient for that rule when used for making information and relationships conveyed through presentation programmatically determinable, so the condition is part of the test rather than a footnote to it.
- ARIA11sufficientAdd landmarks so users can skip around
- ARIA12sufficientUse role=heading when h1-h6 is impossible
- ARIA13sufficientName repeated landmarks so they are distinguishable
- ARIA16sufficientName controls from visible text with aria-labelledby
- ARIA17sufficientGroup related form fields with ARIA roles
- ARIA20sufficientMark leftover page areas with role=region
This guide is our interpretation of W3C technique H43: Using id and headers attributes to associate data cells with header cells in data tables. W3C publishes its techniques as guidance rather than as the standard, and says so on every one of them. The success criterion is what conformance is measured against, and a technique is one documented way to meet it.