Lesson 13 of 30
A sighted user scans a table and instantly connects each cell to its row and column headers. A screen reader reads cell by cell, in order — without explicit markup, it has no idea what any single value means.
13 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
A table uses <td><strong>Name</strong></td> for its header row instead of <th>. Both render bold text that looks identical. What's the accessibility problem?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
Look at a spreadsheet-style table and your eyes do something automatic: they connect the value in a cell to the column header above it and the row label to its left, all in one glance. "42" becomes "42 open tickets, for the Support row."
A screen reader can't replicate that glance. It reads content in a linear order, cell by cell, and by default a cell is just its own text — "42" — with no built-in connection to any header, unless the table's markup makes that connection explicit. Heard in isolation, a sequence of bare values ("42," "Active," "March 2024") tells a screen reader user nothing about what any of them mean.
<!-- Looks identical, means nothing to a screen reader -->
<table>
<tr><td><strong>Name</strong></td><td><strong>Status</strong></td></tr>
<tr><td>Ada</td><td>Active</td></tr>
</table>
<!-- Real header cells, explicitly scoped -->
<table>
<caption>Team member status, updated weekly</caption>
<tr>
<th scope="col">Name</th>
<th scope="col">Status</th>
</tr>
<tr>
<th scope="row">Ada</th>
<td>Active</td>
</tr>
</table>
A table with real <th> header cells, scoped to their column and row.
The first version is a real, common trap: a bold <td> can be made to look pixel-identical to a proper header cell, but it carries none of the semantic information a <th> does — a screen reader has no way to know it's a header at all. The second version fixes that with three specific pieces. <th> marks a cell as a genuine header, not just visually distinct content. scope="col" or scope="row" makes explicit which axis a given header applies to — this matters as soon as a table has headers on both axes, like a data grid with column headers across the top and row labels down the left side, because without scope a screen reader can't tell which relationship a given <th> describes. And <caption> gives the whole table an accessible name and summary, announced before the screen reader starts reading rows — the equivalent of a sighted user reading a table's title before scanning it.
<td> is not a substitute for <th>. They can render identically, but only <th> is exposed to assistive technology as a header — this is one of the most common accessible-table mistakes because it's invisible in a design review.scope becomes necessary, not optional, the moment a table has both row and column headers. A simple single-header-row table can sometimes get away without it, but a data grid with row labels needs scope="row" and scope="col" both present to disambiguate.<caption> is not the same as a heading placed visually above the table. A <h3> sitting outside the <table> element isn't programmatically tied to it; <caption> is a child of <table> itself and is what actually gets announced as the table's name.scope has a real ceiling. A genuinely complex table — merged cells (colspan/rowspan), or headers that span multiple levels — often can't be fully described by scope alone, and needs each data cell's headers attribute to list the ids of every header that applies to it, for fully explicit cell-to-header association.<table> at all — the fix for accidental "table, 12 columns" announcements on a layout grid is CSS layout, not role="presentation" bolted onto real data markup."How would you make a data table screen-reader accessible?" is a real, common question, and naming scope, <caption>, and the headers/id fallback for complex tables — rather than just saying "add ARIA" — is what separates a candidate who's actually built one from one who hasn't.