--- title: "Accessible data tables" category: accessibility status: required url: https://webspecification.com/spec/accessibility/data-tables/ updated: "2026-05-29T10:57:27.000Z" sources: - title: "WCAG 2.2 — 1.3.1 Info and Relationships (Level A)" url: "https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships.html" publisher: "W3C" - title: "HTML Living Standard — Tabular data" url: "https://html.spec.whatwg.org/multipage/tables.html" publisher: "WHATWG" - title: "MDN — : The Table element" url: "https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/table" publisher: "MDN" - title: "Web Accessibility Tutorials — Tables" url: "https://www.w3.org/WAI/tutorials/tables/" publisher: "W3C WAI" - title: "WP Accessibility" url: "https://wpaccessibility.org/" publisher: "WP Accessibility" source_repo: undefined licence: CC-BY-4.0 --- # Accessible data tables > Tabular data must use real
markup with a caption, header cells, and scope attributes so screen readers can announce row and column relationships. ## What it is A data table presents information where each cell only makes sense in the context of its row and its column. The `
` element, together with ``, ``, `` and `
`, `
`, encodes those relationships so that assistive technology can announce them as the user moves between cells. ## Why it matters Sighted users scan a table visually — they see the column heading above a number and the row label to its left at the same time. Screen reader users cannot. They rely on the markup to be told, when they land on `£42`, that this is the **Price** column of the **Hardback** row. Without `` and `scope`, that announcement does not happen and the table becomes a grid of disconnected values. WCAG 1.3.1 Level A requires that information and relationships conveyed visually are also available in the markup. A layout `` or a table built from `
`s fails this criterion. ## How to implement A simple table needs a caption and one row of column headers: ```html
Book prices, May 2026
FormatPrice
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
Q1Q2
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.