FeaturesPricingAudit GuideFree StatementDashboard →

Add Table Headers and Scope Attributes

Learn how to make HTML tables accessible with proper headers and scope attributes. Includes code examples.

6 min read
serious severityWCAG Level AWCAG 2.1 Success Criterion 1.3.1Auto-detectable

What Is It?

Table accessibility requires: <th> tags for headers, scope attribute ("row" or "col") on headers, proper nesting of <thead>, <tbody>, <tfoot>. Screen readers use this structure to announce cell relationships.

Affected users: Screen reader users, cognitively disabled users, users with dyslexia, users on complex data entry

Why It Matters

Without headers and scope, screen reader users hear isolated cell values with no context (e.g., '600' with no indication it's a revenue figure for Q4). Headers make tables understandable.

Good news: Automated tools can detect missing <th> and scope attributes. Proper scope assignment requires understanding table structure.

How to Detect This Issue

Test with screen reader by navigating table cells. Check if headers are announced with cell content. Inspect HTML for <th> tags, scope attributes, and proper table structure.

Automated detection: Run a free SiteArmor scan to automatically detect this issue across your entire website. Check your site →

Code Examples & Fixes

HTML / CSS

Before (inaccessible)
<table>
  <tr><td>Month</td><td>Revenue</td></tr>
  <tr><td>Jan</td><td>$10,000</td></tr>
  <tr><td>Feb</td><td>$12,000</td></tr>
</table>
After (accessible)
<table>
  <thead>
    <tr><th scope="col">Month</th><th scope="col">Revenue</th></tr>
  </thead>
  <tbody>
    <tr><th scope="row">January</th><td>$10,000</td></tr>
    <tr><th scope="row">February</th><td>$12,000</td></tr>
  </tbody>
</table>

Use <th> for headers, scope="col" for column headers, scope="row" for row headers. Screen readers announce: 'January, Revenue, $10,000'.

React / Next.js

Before
const Table = () => <table><tr><td>{data}</td></tr></table>
After
const Table = () => <table>
  <thead><tr><th scope="col">Name</th><th scope="col">Role</th></tr></thead>
  <tbody>{data.map(person => <tr key={person.id}><th scope="row">{person.name}</th><td>{person.role}</td></tr>)}</tbody>
</table>

For dynamic tables, map over data but ensure <th> and scope are properly generated. Use scope="row" for row headers, scope="col" for column headers.

WordPress

Before
Table inserted in WordPress editor, all cells as <td>
After
First row set as header (WordPress editor: highlight row, right-click, "Modify table", mark header). Scope is automatic in WordPress.

WordPress table editor allows marking rows/cells as headers. Use "Modify table" to set header cells properly.

Shopify Liquid

Before
Pricing table built with <div> grid layout, not semantic <table>
After
Pricing table built with proper <table>, <th scope="col"> for pricing column headers, <th scope="row"> for plan names

For data tables, use semantic <table>. If using CSS grid for layout, don't force table semantics. But for data, <table> is correct.

Common Mistakes

Using <td> for headers instead of <th>

Omitting scope attribute from <th> tags

Not nesting <thead>, <tbody>, <tfoot> properly

Complex tables (multi-level headers) without proper structure

Using <table> for layout instead of actual data (don't do this)

Frequently Asked Questions

What's the difference between scope="col" and scope="row"?
scope="col" means this header describes the column below. scope="row" means it describes the row to the right. Use appropriately based on table structure.
What about complex tables with merged cells?
Complex tables should use headers attribute (lists header ids) instead of scope. Example: <td headers="header1 header2"> This gets complex; keep tables simple if possible.
Should I use <caption> in tables?
Yes. <caption> provides a title for the table and is read first by screen readers. Example: <table><caption>Q4 Sales by Region</caption>...
Can I use table for layout?
No. Use CSS Grid or Flexbox instead. Tables are for data. Using tables for layout breaks screen reader navigation and is unmaintainable.

Check your website for free

Get your ADA, WCAG, privacy & security score in 90 seconds.

No credit card
WCAG 2.1
ADA
Privacy

Related guides