• Success Criterion 1.3.1
  • Conformance level A
  • W3C reference F91

Table Header Cells Never Marked Up as Real Headers

1.3.1 — Info and Relationships

Scenario

Setting

A podcast app's episode list

What’s wrong

Data table header cells are not marked up as headers — screen readers can't tell users which column/row a value belongs to.

Example

<table>
  <tr><td>Episode</td><td>Title</td><td>Duration</td></tr>
  <tr><td>12</td><td>Deep Focus</td><td>34:20</td></tr>
</table>

Why it matters

A listener using a screen reader hears every cell read the same way. They can't tell 12 is an episode number, not a duration.

How to test

Click into each header cell in DevTools: it must be a th element (with scope for complex tables) — if it's a styled td, screen reader table navigation won't announce it as a header.

How to fix

The th element is what tells assistive tech a cell is a header, not its position or bold styling.

<table>
  <tr><th>Episode</th><th>Title</th><th>Duration</th></tr>
  <tr><td>12</td><td>Deep Focus</td><td>34:20</td></tr>
</table>

Outcome

A listener hears Episode 12, Deep Focus, Duration 34:20 with each number tied to its meaning.

Who is affected

Screen reader users browsing the episode list have no announced column names to anchor each value to.

Learn more