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

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.