Skip to content
easeweb
Search topics

Data tables with headers that are only bold text

The header row is styled to look like headers, but every cell is a td, so nothing ties a value to its row or column.

WCAG 2.2
SC 1.3.1A
Required by
Section 508 · EN 301 549 (EU)
Broken
Thirty what?
The accessibility problem illustrated.
01

The problem

Screen reader users hear numbers without knowing which row or column they belong to.

02

Try it

Press Tab to move through the prices.

Each Tab stands in for a screen reader moving to the next cell. The panel shows what it announces. Can you tell what each price is for?

Broken Can you fix this?

PlanMonthlyYearly
Starter$12$120
Team$30$300

Screen reader says: (Tab to a price)

A recreated demo. The broken version is intentionally inaccessible.

03

The fix

Mark header cells as headers, and say which way each one reads.

  1. 1Make every header cell a th, or a columnheader or rowheader in a complete ARIA table.
  2. 2Give each th a scope, or each td its headers, never both in one table.
  3. 3Keep layout out of tables, and data tables out of role="presentation".
Before Header cells drawn with td and bold text
<table class="prices">  <tr class="head">    <td>Plan</td>    <td>Monthly</td>    <td>Yearly</td>  </tr>  <tr>    <td class="plan">Starter</td>    <td>$12</td>    <td>$120</td>  </tr>  <tr>    <td class="plan">Team</td>    <td>$30</td>    <td>$300</td>  </tr></table>
After

Th with scope

<table class="prices">  <thead>    <tr>      <th scope="col">Plan</th>      <th scope="col">Monthly</th>      <th scope="col">Yearly</th>    </tr>  </thead>  <tbody>    <tr>      <th scope="row">Starter</th>      <td>$12</td>      <td>$120</td>    </tr>    <tr>      <th scope="row">Team</th>      <td>$30</td>      <td>$300</td>    </tr>  </tbody></table>

Why this fix: Use native HTML first

Fixing this with an AI coding assistant? Get this guide as Markdown

04

Verify the fix

5 checks, no mouse.

Test with: Screen reader, Keyboard, Zoom

0 of 5 checked

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the table component changes.

Limits

This is a starting pattern, not a guarantee for every table. Screen readers differ in how much header text they repeat and when. Tables with headers several levels deep can be hard to follow even with perfect markup; where the data allows, split them into simpler tables.

This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.

Keep this fixed as your code changes.

Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.

How retests work