Website Spec
← Accessibility
Required

Accessible data tables

Tabular data must use real <table> 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 <table> element, together with <caption>, <thead>, <tbody>, <tfoot> and <th>, 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 <th> 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 <table> or a table built from <div>s fails this criterion.

How to implement

A simple table needs a caption and one row of column headers:

<table>
  <caption>Book prices, May 2026</caption>
  <thead>
    <tr><th scope="col">Format</th><th scope="col">Price</th></tr>
  </thead>
  <tbody>
    <tr><th scope="row">Hardback</th><td>£42</td></tr>
    <tr><th scope="row">Paperback</th><td>£18</td></tr>
  </tbody>
</table>

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:

<table>
  <caption>Quarterly revenue by region</caption>
  <thead>
    <tr><td></td><th id="q1" scope="col">Q1</th><th id="q2" scope="col">Q2</th></tr>
  </thead>
  <tbody>
    <tr><th id="eu" scope="row">EU</th>
        <td headers="eu q1">€1.2m</td><td headers="eu q2">€1.4m</td></tr>
  </tbody>
</table>

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:

<div role="region" aria-label="Quarterly revenue" tabindex="0" style="overflow-x:auto">
  <table>…</table>
</div>

Common mistakes

Verification

Sources