Data cells in tables must be associated with their headers

Content available in English only.

Accessibility isn’t just about avoiding violations — it’s about ensuring that everyone can use your product with confidence. This guide explains each rule’s intent, highlights common issues, and shows how to fix them according to WCAG and the European Accessibility Act (EAA).

These guidelines do not replace the official WCAG standards. They’re concise, developer-focused notes to help you identify and fix issues effectively.

If a visual header exists, it must be a <th> with scope — not a styled <td>.

Why this matters and how to fix it

Why this matters

Screen reader users navigate tables by having header cells announced alongside each data cell. If <td> cells are not associated with <th> headers, the table becomes a grid of disconnected values with no meaning. This makes data tables unusable for non-visual users.

How to fix this issue

For simple tables, mark header cells with <th> and use the `scope` attribute (`scope="col"` or `scope="row"`). For complex tables with multiple levels of headers, use `id` on each <th> and reference them with `headers` on each <td>.

Automated detection · Manual review recommended

Developer guidance

This issue often occurs in tables generated from APIs or spreadsheets. Always structure a table with a header row (<th>) before data rows (<td>). For React/Vue table components, enforce header/row semantics at the component level and avoid building tables from <div> elements.


Code examples

Incorrect Implementation

<table>
  <tr><td>Product</td><td>$10</td></tr>
  <tr><td>Service</td><td>$20</td></tr>
</table>

Correct Implementation

<table>
  <tr><th scope="col">Item</th><th scope="col">Price</th></tr>
  <tr><td>Product</td><td>$10</td></tr>
  <tr><td>Service</td><td>$20</td></tr>
</table>

Real-World Examples

Before

<table class="report"><tr><td>Q1</td><td>1200</td></tr><tr><td>Q2</td><td>1500</td></tr></table>

After

<table class="report">
  <caption>Quarterly Sales</caption>
  <tr><th scope="col">Quarter</th><th scope="col">Revenue</th></tr>
  <tr><td>Q1</td><td>1200</td></tr>
  <tr><td>Q2</td><td>1500</td></tr>
</table>

CSS Example (Guidance)

/* Style table headers and data cells for clarity */
th {
  font-weight: 600;
  background-color: #f3f4f6;
  padding: 8px;
}
td {
  padding: 8px;
  border-top: 1px solid #e5e7eb;
}

Manual testing

  1. 1. Inspect the table in browser dev tools.
  2. 2. Ensure header cells use <th>, not <td> styled to look bold.
  3. 3. For simple tables: Check that each <th> includes `scope="col"` or `scope="row"`.
  4. 4. For complex tables: Ensure <th> elements have unique `id` attributes and <td> cells reference those IDs using `headers`.
  5. 5. Test with a screen reader (NVDA, VoiceOver): Navigate cell-by-cell and verify the associated header is read aloud each time.
eu icon getwcag

Trusted by organizations across Europe working toward WCAG and EAA conformance