Zum Inhalt springen
BFSG compliance since 2025

Accessible Data Tables and Complex Content

13 min read
DatentabellenWCAG 1.3.1ScreenreaderSemantikHTML

Tables are among the most important tools for organizing data clearly - and at the same time among the most frequently mis-marked-up structures on the web. Prices by plan, timetables, comparison matrices or financial figures: visually the eye recognizes the relationship between header and cell instantly. A screen reader, by contrast, reads each cell individually and depends on the relationship between header and data cell being encoded technically. How rarely this succeeds is shown by the WebAIM Million Report: only 16.8% (WebAIM Million, 2024) of the over one million detected tables had valid data table markup. This guide shows how to build tables with th, scope, caption and, for complex tables, headers and id so that the relationships are preserved programmatically - as a solid basis for your accessible web development.

Accessible Data Table: caption, th with scope and programmatic relationshipscaption: Prices by plan and termcaptionPlanMonthlyYearlySupportscope=colscope=colscope=colscope=colBasicProTeam9 EUR19 EUR39 EUR90 EUR190 EUR390 EUREmailChatPhoneth scope=row<table><caption>Prices by plan</caption><th scope="col">Monthly</th><th scope="row">Basic</th><td headers="..."> for complex tables</td></table>Screen reader announcesthe cell with context, not just the valueColumn Monthly, row Pro: 19 EURColumn Support, row Team: PhoneWCAG 1.3.1 checklistth instead of td for header cellsscope=col and scope=row setcaption as the table titleLayout tables without th and captionComplex tables: headers and idResponsive without losing relationsOnly 16.8 percent of over 1 million detected tables had valid data table markup (WebAIM Million, 2024)

Why Data Tables So Often Fail on Accessibility

For sighted users a table is a two-dimensional grid: the eye jumps between column header, row header and data cell and establishes the relationship almost incidentally. A screen reader has no such spatial overview. It reads cell by cell and must know, for each data cell, which column and row header it belongs to. This is exactly the relationship that WCAG 1.3.1 Info and Relationships demands: information, structure and relationships conveyed visually must be programmatically determinable (W3C/WAI). Without the markup, the user hears a sequence of disconnected values.

Practice shows how large the gap is. In the WebAIM Million Report, 95.9% (WebAIM Million, 2024) of all home pages analyzed in 2024 had detectable WCAG failures, averaging 56.8 (WebAIM Million, 2024) per page - an increase of 13.6% (WebAIM Million, 2024) over the previous year. Tables are a problem case of their own: if only 16.8% (WebAIM Million, 2024) of tables are validly marked up at all, the majority remain incomprehensible to assistive technologies. In Germany this affects many people directly: at the end of 2023 around 7.9M (Federal Statistical Office, 2024) people with severe disabilities lived here, and worldwide around 2.2B (WHO, 2023) people have a vision impairment.

A table is not automatically a data table

The table element alone says nothing about the relationship of the cells. Only header cells with th, the scope attribute and a caption turn a grid into a programmatically understandable data table. Without this markup a screen reader reads only a sequence of values without relationship (W3C/WAI).

The Building Blocks of an Accessible Data Table

An accessible data table emerges from the interplay of a few clearly defined building blocks. The following overview summarizes what the Tables Tutorial of the Web Accessibility Initiative and WCAG 1.3.1 require (W3C/WAI). We check these points systematically as part of our services.

th for header cells

Header cells are marked up with th, data cells with td. This lets assistive technology distinguish heading from content.

scope attribute

scope=col and scope=row define whether a header cell applies to a column or a row. It is the simplest form of association.

caption

The caption gives the table a visible title and serves screen readers as a landmark. It comes directly after the table tag.

headers and id

For complex tables, unique id values on th and the headers attribute on td link each cell to its headers.

thead, tbody, tfoot

These structural elements group the header, body and footer area and improve navigation and understanding of the table.

No layout tables

Misusing tables purely for layout is a WCAG failure as soon as they contain th, caption or summary (W3C/WAI, F46).

For most tables the combination of th, scope and caption is fully sufficient. Only when header cells span several columns or rows, or when multiple heading levels interlock, do headers and id come into play. This semantic markup builds on the same foundations we cover in detail in our article on screen reader optimization for websites.

Simple Tables: th, scope and caption

The most common type of table has exactly one row of column headers, often complemented by a column of row headers. Here it is enough to mark up the header cells with th and indicate the direction with scope: scope=col for column headers, scope=row for row headers. The screen reader then reads the matching headers for each data cell - for example column Monthly, row Pro, value 19 Euro. The caption gives the whole table a title that assistive technologies offer as an entry point.

simple-table.html
<table>
  <caption>Prices by plan and term</caption>
  <thead>
    <tr>
      <th scope="col">Plan</th>
      <th scope="col">Monthly</th>
      <th scope="col">Yearly</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Basic</th>
      <td>9 Euro</td>
      <td>90 Euro</td>
    </tr>
    <tr>
      <th scope="row">Pro</th>
      <td>19 Euro</td>
      <td>190 Euro</td>
    </tr>
  </tbody>
</table>

scope is the underrated key

Many tables do use th but forget scope. Without scope, screen readers have to guess the association, which goes wrong with multi-column tables. The attribute scope=col or scope=row costs almost no effort and makes the relationship unambiguous (W3C/WAI).

Complex Tables: Linking headers and id Correctly

As soon as header cells span several columns or rows (colspan, rowspan) or several heading levels exist, scope is no longer enough. Then the association is no longer strictly horizontal or vertical, and the relationship has to be established explicitly (W3C/WAI). For this, each header cell gets a unique id, and each data cell lists in its headers attribute the id values of all headers that apply to it - separated by spaces when there are several. The screen reader then reads exactly the associated headers for each cell and does not lose context.

complex-table.html
<table>
  <caption>Revenue by region and quarter</caption>
  <tr>
    <td></td>
    <th id="q1" scope="col">Q1</th>
    <th id="q2" scope="col">Q2</th>
  </tr>
  <tr>
    <th id="north" scope="row">North</th>
    <td headers="north q1">120</td>
    <td headers="north q2">140</td>
  </tr>
  <tr>
    <th id="south" scope="row">South</th>
    <td headers="south q1">95</td>
    <td headers="south q2">110</td>
  </tr>
</table>

It is important to avoid complex tables where possible: nested headers can often be split into several simple tables, each of which works with scope alone. A simple, clearly structured table is not only easier to mark up but also more understandable for all users. Correctly linking multiple relationships via id and headers is closely related to the clean assignment of roles and states described in our article on ARIA roles, states and live regions.

Table typeSuitable markupTypical mistake
Simple table (one header row)th with scope=col, optionally scope=row, captiontd instead of th for headers, no scope
Table with row and column headerth scope=col plus th scope=row, captionscope missing, relationship only visual
Complex table (colspan/rowspan)unique id on th, headers on tdnested th without headers/id
Layout table (visual only)better CSS grid/flexbox, no th/captionth, caption or summary in layout (F46)
Responsive table (mobile)preserve relationships, do not dissolvehiding columns, relationships are lost

Layout Tables vs. Data Tables

Historically, tables were often misused to lay out pages - with rows and columns as a design grid instead of a data structure. Today this is a recognized failure: a table that serves only the layout but contains th elements, a caption or a non-empty summary attribute violates WCAG 1.3.1 because it uses semantic markup purely for presentation (W3C/WAI, F46). Screen readers announce such a table as a data table and confuse the user with row and column announcements where there is no data at all.

The rule is simple: use table markup only for genuinely tabular data. For pure layout, CSS grid and flexbox are the right choice because they separate presentation from structure and retain the semantic meaning of the HTML table elements (W3C/WAI). If a layout table is exceptionally necessary, it must contain neither th nor caption nor summary and should be neutralized with role=presentation. The clean separation of content and presentation is also a central topic in our article on accessible forms and validation.

Real data deserves real tables

A data table is the right choice when values only gain meaning through their row and column membership - such as a price that belongs to a plan and a term. If it is only about placing things side by side, a CSS layout is the more accessible and maintainable solution.

Responsive Tables and Very Wide Data Sets

Wide data tables are a challenge on small screens. The most common but problematic solution hides columns on mobile or breaks the table into cards - and often loses the relationship between header and value in the process. This is exactly what the Tables Tutorial of the Web Accessibility Initiative warns against: stacking or hiding columns must not destroy the programmatic relationships (W3C/WAI). If a responsive layout turns a table into a stacked layout, the headers must remain available for each value.

Two approaches have proven effective: first, keeping the table in a horizontally scrollable container so its structure stays untouched - the container should be keyboard focusable and given an accessible name. Second, with a card layout, visually repeating the header per value, for instance via data attributes and CSS, so it remains clear which value belongs to what. From supporting 50+ (project experience) projects we know that most table problems arise not on the desktop but in the mobile implementation - where columns are simply hidden under time pressure.

Common mistake: simply hiding columns

If a column is hidden on mobile via display:none, it disappears for the screen reader too - including possibly important information. Horizontal scrolling or a card layout that keeps the headers per value is better. Whether the relationship is actually preserved only shows in a manual test with a screen reader.
  • Header cells marked up with th instead of td
  • scope=col and scope=row set for the direction of the headers
  • caption present as a visible table title
  • Complex tables linked via unique id and headers
  • thead, tbody and, where applicable, tfoot used for grouping
  • Layout tables avoided or neutralized with role=presentation
  • Responsive without losing the header-value relationship
  • Verified with keyboard and screen reader

A table is only accessible once every value knows its header. Whoever builds only the grid but forgets the relationship delivers numbers without meaning.

Principle from the audit practice of accessible web development

Data tables touch above all WCAG 1.3.1 Info and Relationships, because here the entire column and row logic must be programmatically available (W3C/WAI). Since automated testing tools can only test about one third to one half of WCAG requirements at all (W3C/WAI), it only shows in a manual test with a screen reader whether a table really conveys its relationships. Whoever builds tables from the start with th, scope, caption and, where needed, headers and id avoids an entire class of recurring errors - and creates a reliable basis for the WCAG audit. We cover related patterns for dynamic and overlaying content in our articles on accessible modals and overlays and accessible error messages and status messages.

This article is based on data from: the W3C Web Content Accessibility Guidelines (WCAG) 2.2, success criterion 1.3.1 Info and Relationships, the Tables Tutorial and technique F46 of the W3C Web Accessibility Initiative, MDN Web Docs (table, th, scope, headers), the WebAIM Million Report (2024), the German Federal Statistical Office (2024) and the World Health Organization WHO (2023).