Accessible Tables
Accessible tables use semantic table markup and explicit header associations so assistive technologies can understand how data cells relate to their headers. For frontend work, prefer native `<table>`, `<th>`, and appropriate `scope` attributes over visually styled generic elements.
A data table represents relationships between rows and columns. Use `<table>` for genuinely tabular data, `<tr>` for rows, `<th>` for header cells, and `<td>` for data cells. A `<caption>` can provide the table's accessible name or context when useful.
The `scope` attribute makes common header relationships explicit. Use `scope="col"` for a header describing a column and `scope="row"` for a header describing a row. This is especially useful when a table has multiple dimensions that users need to navigate.
Keep header cells and data cells semantically distinct. Do not use `<td>` elements merely because they can be styled to look like headers, and do not replace a table with nested `<div>` elements when the content actually represents rows and columns.
Simple tables often need only native semantics plus correct `scope` values. More complex tables, such as those with grouped or irregular headers, may require additional associations such as `id` and `headers`; the goal is to preserve an unambiguous relationship between every data cell and its relevant headers.
Key points
- Use `<table>` for tabular data and `<th>` for headers.
- Use `scope="col"` for column headers and `scope="row"` for row headers.
- Use `<caption>` when a table benefits from a clear title or description.
- Prefer native table semantics over recreating tables with generic elements.
- For complex header structures, use explicit header associations when `scope` is insufficient.
Interview questions
When would `headers` and `id` be preferable to `scope`?
They are useful when header relationships cannot be represented cleanly as simple row or column scopes. A header cell receives an `id`, and a data cell can reference the applicable headers through its `headers` attribute. This provides explicit cell-to-header associations for complex or irregular tables, where relying on inferred relationships could be ambiguous.
How would you make a simple data table accessible?
I would start with native table markup: `<table>`, an optional `<caption>`, table sections where useful, `<th>` for headers, and `<td>` for data. I would use `scope="col"` and `scope="row"` where the relationships are straightforward. I would also check the resulting structure with keyboard and assistive-technology testing rather than relying only on visual appearance.
Why should you use `<th>` instead of a styled `<td>` for a table header?
`<th>` has native table-header semantics, so assistive technologies can identify it as a header. A styled `<td>` only changes presentation and does not establish the same semantic relationship. Using the correct element also makes the HTML structure clearer to developers and browser tooling.
What does the `scope` attribute do on a table header?
`scope` tells the user agent what set of cells a header describes. `scope="col"` associates a header with its column, while `scope="row"` associates it with its row. This makes common table relationships explicit and easier for assistive technologies to interpret.