Structure & headings
Data Cells in a Large Table Have No Header
In a big table, screen reader users hear each value with no row or column name, so they can't tell what the numbers mean.
td-has-headerWCAG 2.0Introduced in WCAG 2.0.Level AA — the minimum. Missing it blocks people outright.
- Status
- SeriousSerious — Significant friction, or information that is lost.Experimentalaxe-core has this rule, but runs it only when a team turns experimental rules on.
- Owner
- DesignDevContentTest
- Audit
- Automated+ManualA scanner finds it; a person confirms the fix.
Experimental rule. Experimental in axe-core: it runs only when a team turns experimental rules on, so a clean default scan says nothing about it. WCAG 1.3.1 Info and Relationships still applies.
Why it matters
Sighted people glance up to the column header and across to the row label. Screen reader users can't. They rely on headers marked in the code, which the screen reader reads out with each cell.
In a table of 3 by 3 or larger, without headers, every cell is just a bare value — "42", "Yes", "$80". People must count rows and columns in their head to make sense of it.
Who it affects
| Who | What they experience | Impact |
|---|---|---|
| Screen reader users | They hear "42" as they move through cells, with no column or row name to explain it. | High impact |
| Low-vision users (magnification) | At high zoom they may lose sight of the headers and rely on a screen reader to fill the gap. | Partial impact |
| Cognitive and neurodivergent users | Affected only if they use read-aloud tools, which also need the headers marked up. | Partial impact |
Business & product impact
| Area | Why | Impact |
|---|---|---|
| Legal | It fails WCAG 2.2 criterion 1.3.1 at Level A, the minimum. Complaints under Australia's Disability Discrimination Act and EN 301 549 point to it. | High impact |
| Conversion | Pricing, plan comparison and timetable tables become unusable, so people can't choose or buy. | Moderate impact |
| SEO | Little or no search benefit — don't sell it as one. | Low impact |
| Brand trust | Unreadable tables in reports or statements look careless to the people who rely on them. | Low impact |
| Cost to fix | Usually a small markup change. Fix it in the shared table component and every table benefits. | Moderate impact |
Fixing it in code
A plan comparison table
Don't
<table>
<tr><td>Plan</td><td>Price</td><td>Users</td></tr>
<tr><td>Basic</td><td>$10</td><td>1</td></tr>
<tr><td>Team</td><td>$40</td><td>10</td></tr>
</table>A screen reader says: “$40”
Do
<table>
<tr><th scope="col">Plan</th><th scope="col">Price</th><th scope="col">Users</th></tr>
<tr><th scope="row">Basic</th><td>$10</td><td>1</td></tr>
<tr><th scope="row">Team</th><td>$40</td><td>10</td></tr>
</table>A screen reader says: “Team, Price, $40”
th with scope tells the screen reader which headers belong to each cell.
A table used only for layout
Don't
<table>
<tr><td>Logo</td><td>Menu</td><td>Search</td></tr>
<tr><td>Intro</td><td>News</td><td>Events</td></tr>
<tr><td>Footer</td><td>Links</td><td>Contact</td></tr>
</table>A screen reader says: “Table, 3 rows, 3 columns. News”
Do
<div class="grid">
<div>Logo</div><div>Menu</div><div>Search</div>
<div>Intro</div><div>News</div><div>Events</div>
<div>Footer</div><div>Links</div><div>Contact</div>
</div>A screen reader says: “News”
If it isn't data, don't use a table — use CSS grid for layout.
Designer's handoff note
In every data table design, mark which row and which column hold the headers.
Avoid tables with no visible headers. If a header is truly obvious, it still needs to exist in the code.
Quick test
Tool
NVDA (opens in a new tab) (free, Windows)
Duration
2 minChecklist
- Pass
- You hear the row or column header before the value, like "Team, Price, $40".
- Fail
- You hear only the value, like "$40".
Check these at the same time
- A table header cell has no text
empty-table-header - A table's scope attribute is in the wrong place or misspelt
scope-attr-valid - A table cell's headers attribute points to the wrong cells
td-headers-attr - A table header has no data cells under or beside it
th-has-data-cells
What a green scan still misses
A scanner checks that headers exist. It can't tell whether they are the right cells, or whether the header text makes sense when read aloud.
Reference
- Status
- ExperimentalExperimental in axe-core: it runs only when a team turns experimental rules on, so a clean default scan says nothing about it. WCAG 1.3.1 Info and Relationships still applies.
- Rule ID
td-has-header- Raised by
- axe-core: “Non-empty <td> elements in larger <table> must have an associated table header”
- WCAG
- 1.3.1 Info and Relationships (opens in a new tab) · Level A · since WCAG 2.0
- Other standards
- EN 301 549 9.1.3.1 · RGAA 5.7.4
- Last reviewed
- 16 October 2026