`s fails this criterion.
## How to implement
A simple table needs a caption and one row of column headers:
```html
Book prices, May 2026
| Format | Price |
| Hardback | £42 |
| Paperback | £18 |
```
When headers span groups of rows or columns, use `scope="rowgroup"` and `scope="colgroup"`. When the structure is genuinely complex — multiple levels of headers, headers that don't line up — switch to the `id` and `headers` pattern:
```html
Quarterly revenue by region
| Q1 | Q2 |
| EU |
€1.2m | €1.4m |
```
For long extra context that won't fit in the caption, use `aria-describedby` pointing to a paragraph nearby.
Wide tables on narrow screens should scroll horizontally as a focusable region, so keyboard users can reach the off-screen columns:
```html
```
## Common mistakes
- Using `
` for page layout or for form field alignment. Use CSS Grid or Flexbox instead.
- `| ` cells with bold text standing in for headers, with no ` | `.
- A header row with no `scope` attribute — ambiguous for nested tables and complex headers.
- Hiding the caption with `display: none`; it is then also removed from the accessibility tree. Use a visually hidden class if you must.
- Setting `overflow-x: auto` on a ` ` with no `tabindex` — mouse users can scroll, keyboard users cannot.
## Verification
- Tab through the table with a screen reader (VoiceOver, NVDA). Each data cell should be announced with its row and column header.
- Check the accessibility tree in DevTools. Headers should appear as `columnheader` or `rowheader`, not `cell`.
- Run an automated checker (axe, Lighthouse). It will flag missing ` | `, missing `scope`, and layout tables.
- Disable CSS. The table should still read top-to-bottom in a sensible order.
|