</>
ValidateHTML

Missing Table Headers

Data tables need <th> (table header) elements to identify what each column or row represents. Screen readers use these headers to announce the context for each cell. Without headers, a screen reader just reads cell values in sequence with no indication of what column or row they belong to.

Find this error in your own code. Paste your HTML or enter a URL, free and instant.Open the checker
0.8%
of sites tested

How common is this error?

We ran this validator over the home page of the Tranco top 5,000 websites in August 2026. 22 of the 2,655 sites we could reach hit it. That makes it the 9th most common accessibility problem we found, across 329 occurrences. See the full study.

Most frequent wording: <th> element must have a valid scope attribute: row, col, rowgroup or colgroup

Why It Matters

A data table without headers is nearly useless for screen reader users. They hear a stream of values with no context. This is a WCAG 2.1 Level A violation. It's especially problematic for complex tables with many columns where context is essential to understand the data.

Common Causes

  • Building the header row with <td> cells and bold styling instead of real <th> elements.
  • Omitting the scope attribute, so the screen reader cannot tell whether a header applies to a column or a row.
  • Using a <table> for visual layout rather than data, which mixes presentation with a structure meant for tabular data.

Code Examples

Inaccessible
<table>
  <tr>
    <td>Name</td>
    <td>Email</td>
    <td>Role</td>
  </tr>
  <tr>
    <td>Alice</td>
    <td>alice@example.com</td>
    <td>Developer</td>
  </tr>
</table>
Accessible
<table>
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">Email</th>
      <th scope="col">Role</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Alice</td>
      <td>alice@example.com</td>
      <td>Developer</td>
    </tr>
  </tbody>
</table>

How to Fix

  • 1Use <th> elements for header cells instead of <td>.
  • 2Add scope="col" for column headers and scope="row" for row headers.
  • 3Wrap header rows in <thead> and data rows in <tbody> for clarity.
  • 4For complex tables, use the headers attribute on <td> elements to reference specific <th> ids.

Frequently Asked Questions

Why are <th> elements better than bold <td> cells?
Visual boldness means nothing to a screen reader. A <th> programmatically marks a cell as a header, so assistive technology can announce the relevant column or row header before each data cell, giving the values context that styled <td> cells cannot.
When should I use scope="col" versus scope="row"?
Use scope="col" for a header that labels everything in its column (the top row) and scope="row" for a header that labels everything in its row (often the first cell of each row). Scope tells screen readers which direction the header applies.
Should I use a table for page layout?
No. Use CSS grid or flexbox for layout. Layout tables force screen readers to announce meaningless rows and columns. Reserve <table> for genuine tabular data, where headers and scope give the structure real meaning.

Check Your Accessibility Now

Our accessibility checker detects this issue automatically.

Open Accessibility Checker

Related Accessibility Errors

View all accessibility errors