WCAG 1.3.1Info and Relationships

Missing Table Headers

What is this issue?

Missing table headers occur when data tables use <td> elements for all cells without using <th> elements to identify row and column headers. WCAG Success Criterion 1.3.1 (Level A) requires that information and relationships conveyed through visual presentation are also programmatically determinable. For data tables, this means header cells must be marked up with <th> and associated with their data cells so assistive technologies can announce the context of each cell.

When a screen reader user navigates a data table, the software announces the column and row headers as the user moves between cells. Without <th> elements, the screen reader can only announce the cell content with no context. A user hearing "$4,500" has no idea whether that is a price, a quantity, a revenue figure, or a date unless the header relationship is established.

This issue is especially common in tables generated by CMS plugins, JavaScript frameworks, and data visualization libraries. Many table components render all cells as <td> and rely solely on visual styling (bold text, background color) to distinguish headers from data. Some developers avoid tables entirely and use CSS grids to create table-like layouts, which removes all semantic table structure.

Impact on users

For screen reader users, navigating a data table without headers is like looking at a spreadsheet where all the column and row labels have been deleted. Each cell value is meaningless without context. A table of employee information where the user hears "John, Smith, Engineering, 2019" is only useful if the headers "First Name, Last Name, Department, Start Year" are announced alongside each value.

Complex tables with merged cells or multi-level headers are even more problematic without proper markup. The scope attribute on <th> elements (scope="col", scope="row") and the headers attribute on <td> elements establish these relationships. Without them, complex table data is completely inaccessible.

Data tables are used extensively in business applications, financial reports, product comparisons, and scheduling tools. Missing headers in these critical contexts can prevent users from performing their job duties, making purchasing decisions, or accessing essential information.

Code example

Before (non-compliant)
<!-- Table without header markup -->
<table>
  <tr>
    <td><b>Product</b></td>
    <td><b>Price</b></td>
    <td><b>Stock</b></td>
  </tr>
  <tr>
    <td>Widget A</td>
    <td>$29.99</td>
    <td>142</td>
  </tr>
  <tr>
    <td>Widget B</td>
    <td>$49.99</td>
    <td>38</td>
  </tr>
</table>
After (compliant)
<!-- Table with proper headers and caption -->
<table>
  <caption>Current product inventory</caption>
  <thead>
    <tr>
      <th scope="col">Product</th>
      <th scope="col">Price</th>
      <th scope="col">Stock</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Widget A</th>
      <td>$29.99</td>
      <td>142</td>
    </tr>
    <tr>
      <th scope="row">Widget B</th>
      <td>$49.99</td>
      <td>38</td>
    </tr>
  </tbody>
</table>

How Scrutia detects this issue

Scrutia identifies all data tables on your pages and checks for the presence of <th> elements with appropriate scope attributes. It flags tables that use <td> for header cells, tables with complex structures lacking headers attributes, and layout tables incorrectly using data table markup. The report includes the table location and a corrected markup example.

Check your site for this issue

Scrutia audits your site against WCAG criteria in minutes.

Free audit

Frequently Asked Questions

When should I use scope vs. headers attributes?
Use scope="col" or scope="row" on <th> elements for simple tables with a single level of headers. For complex tables with merged cells or multi-level headers, use the headers attribute on <td> elements to explicitly reference the id of each associated <th>.
Should layout tables have headers?
No. Tables used purely for visual layout should not have <th> elements, <caption>, or summary attributes. Better yet, avoid layout tables entirely and use CSS for layout. If you must use a layout table, add role="presentation" to remove its table semantics.
What is the purpose of the <caption> element?
The <caption> element provides a title or description for the table. Screen readers announce it when the user encounters the table, providing context before they navigate into the cells. It is the table equivalent of a heading.

Does your site have this issue?

Scrutia scans your pages against WCAG success criteria and delivers actionable fixes. Results in 5 minutes.

Run a free audit