← Back to Blog

HTML tables without headers are invisible to screen readers

HTML tables without headers are invisible to screen readers

Tables are one of the oldest HTML elements, and they're still the right tool for tabular data. Pricing grids, comparison charts, schedule matrices, specification lists. The problem isn't that people use tables. The problem is that most tables are built for sighted users only.

When a screen reader encounters a <table> element, it shifts into table navigation mode. The user can press arrow keys to move between cells, and the screen reader announces the column header for each cell so the user knows what data they're looking at. But this only works if the table has actual <th> elements with proper scope attributes. Without them, the screen reader just reads cell contents in sequence with no context. "42. Yes. $19.99. Monthly." That's what your pricing table sounds like to a blind user when the headers are missing.

The three things most tables get wrong

Missing <th> elements. The most common problem is using <td> for header cells instead of <th>. Developers style the top row with bold text and a background color and assume that's enough. Visually it looks like a header. Programmatically it's just another data cell. Screen readers have no way to distinguish it from the content below.

Missing scope attributes. Even when <th> is used, omitting scope="col" or scope="row" forces screen readers to guess which cells the header applies to. Simple tables with a single header row usually get guessed correctly. But any table with both row headers and column headers, or headers that span multiple columns, needs explicit scope declarations. Without them, the screen reader might announce the wrong header for a cell, which is worse than announcing none at all.

Missing <caption>. A table caption serves the same purpose as an image's alt text. It tells assistive technology what the table is about before the user starts navigating it. A sighted user can glance at surrounding text for context. A screen reader user landing on a table mid-page has no context unless the caption provides it. "Table: Monthly pricing by plan tier" tells the user what to expect. Silence doesn't.

What the spec actually requires

WCAG 2.1 Success Criterion 1.3.1 (Info and Relationships) requires that information and relationships conveyed through presentation are programmatically determinable. For tables, this means header cells must be marked as headers, and the association between headers and data cells must be explicit.

This is a Level A criterion. Not AA. Not AAA. Level A, the absolute baseline. A table without proper headers fails the most fundamental level of the Web Content Accessibility Guidelines.

HTML also provides <thead>, <tbody>, and <tfoot> elements for structural grouping. While their accessibility impact is smaller than <th> and scope, they help screen readers understand table regions and provide navigation landmarks within large tables. Using them costs nothing and adds a layer of semantic clarity.

For complex tables where a cell is associated with headers in non-obvious ways, the headers attribute on <td> elements lets you explicitly list the IDs of all header cells that apply. This is rarely needed for simple grids but essential for tables with merged cells or multi-level headers.

What the Table Accessibility Audit checks

The Table Accessibility Audit scans every <table> element on your page and checks four things:

Does the table have at least one <th> element? If the entire table uses <td> for every cell, including the header row, it's flagged immediately.

Do the <th> elements have scope attributes? The audit checks for scope="col" on column headers and scope="row" on row headers. Missing scope on any <th> is reported as a warning.

Does the table have a <caption> element? Tables without captions get flagged. An aria-label or aria-labelledby on the <table> element is accepted as an equivalent.

Are <thead> and <tbody> used for structural grouping? This is reported as a best-practice suggestion rather than a failure, since the accessibility impact is smaller, but it's still worth knowing.

The audit generates a fix prompt that includes the specific HTML structure of each failing table, so you can paste it into your editor or an AI assistant and get a corrected version with all the headers, scopes, and captions in place.

How to fix it

For a typical pricing table with plans across the top and features down the left side:

<table>
  <caption>Monthly pricing by plan tier</caption>
  <thead>
    <tr>
      <th scope="col">Feature</th>
      <th scope="col">Basic</th>
      <th scope="col">Pro</th>
      <th scope="col">Enterprise</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Storage</th>
      <td>5 GB</td>
      <td>50 GB</td>
      <td>Unlimited</td>
    </tr>
  </tbody>
</table>

That's it. <th> for headers, scope to declare direction, <caption> for context. The visual presentation doesn't change at all. You're just adding the semantic information that screen readers need.

If you're building comparison tables or data grids for a product site, The $97 Launch covers accessible markup patterns for common page types so these details are baked in from the start.

Fact-check notes and sources

  • WCAG 2.1 SC 1.3.1 Info and Relationships: W3C WCAG 2.1, Level A.
  • W3C Tables Tutorial with scope and headers examples: W3C WAI Tables Tutorial.
  • WebAIM's 2024 accessibility analysis of the top 1 million home pages found that 23.5% of tables lacked any header markup.

Related reading

This post is informational, not accessibility-consulting or legal advice. Mentions of WCAG and W3C are nominative fair use. No affiliation is implied.

← Back to Blog

Accessibility Options

Text Size
High Contrast
Reduce Motion
Reading Guide
Link Highlighting
Accessibility Statement

J.A. Watte is committed to ensuring digital accessibility for people with disabilities. This site conforms to WCAG 2.1 and 2.2 Level AA guidelines.

Measures Taken

  • Semantic HTML with proper heading hierarchy
  • ARIA labels and roles for interactive components
  • Color contrast ratios meeting WCAG AA (4.5:1)
  • Full keyboard navigation support
  • Skip navigation link
  • Visible focus indicators (3:1 contrast)
  • 44px minimum touch/click targets
  • Dark/light theme with system preference detection
  • Responsive design for all devices
  • Reduced motion support (CSS + toggle)
  • Text size customization (14px–20px)
  • Print stylesheet

Feedback

Contact: jwatte.com/contact

Full Accessibility StatementPrivacy Policy

Last updated: April 2026