Info Table missing caption or header scope

Why data tables need a <caption> and scope attributes on <th> cells, and what screen readers do without them.

This covers two related table accessibility issues: a <table> with no <caption> child (table-missing-caption), and a table containing <th> cells where none carry a scope attribute (table-th-missing-scope).

Example

<table>
  <caption>Monthly active users by region</caption>
  <thead>
    <tr>
      <th scope="col">Region</th>
      <th scope="col">Users</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">EU</th>
      <td>12,400</td>
    </tr>
  </tbody>
</table>

Why it matters

A <caption> gives a table an accessible name that a screen reader announces before reading its contents, the same way a heading introduces a section — without one, a table is just an unlabeled grid of cells with no context for what it represents. scope="col" or scope="row" on a <th> tells assistive technology which cells that header describes; browsers can often infer this correctly for simple tables, but anything with merged cells, multiple header rows, or an irregular structure needs it stated explicitly, or header association has to be guessed.

Frequently asked questions

Do I need scope on every single <th>?

Just enough that a screen reader can resolve every data cell to its header — in a simple table with one header row and/or column, scope on those header cells is enough; this check simply flags tables where none of the <th> cells have it at all.

Is <caption> the same as a heading above the table?

No — a heading before a <table> is not programmatically associated with it, so a screen reader user navigating cell-by-cell has no way to hear it. <caption> is inside the table itself and is explicitly tied to it by the HTML spec.