Skip to content

A11Y Cheat Sheet

Powered byA11y University

Structure & headings

A Table's Scope Attribute Is in the Wrong Place or Misspelt

When `scope` is on the wrong cell or has a made-up value, screen readers can't tell which header goes with each cell, so numbers lose their meaning.

scope-attr-validBest practiceBest practice — not a WCAG requirement, but it helps people all the same.

Status
ModerateModerate — An annoyance, with a workaround.CurrentScanners run this rule today.
Owner
DevContentTest
Audit
Automated+ManualA scanner finds it; a person confirms the fix.

Why it matters

In a data table, scope tells a screen reader whether a header labels a column or a row. Then, as someone moves cell by cell, they hear the right header with each value.

scope only works on header cells (th), with one of four values: col, row, colgroup or rowgroup. Anything else is ignored. People then hear a bare "$20" and have to guess what it means.

Who it affects

Who it affects, and how much
WhoWhat they experienceImpact
Screen reader usersThey hear a value like "$20" with no header, so they must count rows and columns to work out what it is.High impact
Low-vision users (magnification)Affected only if they also use a screen reader. Magnifier users see the table as normal.Partial impact

Business & product impact

Business & product impact, with how much each claim weighs
AreaWhyImpact
LegalThis rule is a best practice, not a WCAG requirement on its own. But if headers end up unlinked from their data, that can fail WCAG 2.2 Level AA, which Australian Disability Discrimination Act complaints point to.Moderate impact
ConversionPricing, plan and comparison tables drive decisions. If people can't follow them, some will leave or call instead.Moderate impact
SEOSearch engines don't reward correct `scope` — don't sell it as an SEO fix.Low impact
Brand trustA broken comparison table tells screen reader users the site wasn't built for them.Low impact
Cost to fixUsually a quick edit in the table markup or the table component. Fix the component once.High impact

Fixing it in code

Scope on an ordinary cell

Don't

<tr><td scope="col">Plan</td><td scope="col">Price</td></tr>
<tr><td>Basic</td><td>$20</td></tr>

A screen reader says: “$20”

Do

<tr><th scope="col">Plan</th><th scope="col">Price</th></tr>
<tr><td>Basic</td><td>$20</td></tr>

A screen reader says: “Price, $20”

scope only works on th header cells, so make the headers real th elements.

A made-up scope value

Don't

<th scope="column">Price</th>
<th scope="horizontal">Basic</th>

A screen reader says: “$20”

Do

<th scope="col">Price</th>
<th scope="row">Basic</th>

A screen reader says: “Basic, Price, $20”

Only col, row, colgroup and rowgroup are understood; anything else is ignored.

Designer's handoff note

In table designs, mark which cells are column headers and which are row headers. Developers then know where th and scope belong.

Only use a table for data with rows and columns, not for page layout.

Quick test

Tool

NVDA (opens in a new tab) (free, Windows)

Checklist

Pass
You hear the right header with each value, like "Price, $20".
Fail
You hear only the value, like "$20", or the wrong header.

What a green scan still misses

A scanner checks that scope is on a th with a valid value. It can't tell if you chose col where you meant row — for that, listen.

Reference

Rule ID
scope-attr-valid
Raised by
  • axe-core: “scope attribute should be used correctly”
WCAG
Best practice — not a WCAG requirement
Last reviewed
14 October 2026