Table headers must have associated data cells
Estimated effort: about 10 minutes.
A <th> element is meant to be a header for one or more actual data cells in a table. If a table's headers are marked up incorrectly — for example a <th> that uses a headers attribute pointing nowhere, or a table where header relationships aren't defined through scope at all — screen readers can't announce which header belongs to which row of data, which matters most on an order-history table with many rows of dates, statuses, and totals.
How to fix it
- Find data tables where header cells (<th>) don't clearly connect to the data cells (<td>) below or beside them, commonly an order-history table listing past orders with columns like Order, Date, Status, and Total.
- For simple tables with one row of column headers and no merged cells, add scope="col" to each <th> in the header row, and scope="row" to any <th> used as a row header (for example an order number acting as the row label).
- Only use <th> elements for actual headers — do not use a <th> for a cell that is just visually bold or styled to look like a header, and do not leave a <th> present with no data cells for it to describe.
- If a <th> uses the headers attribute rather than scope, make sure it is not required to have the attribute at all — per this rule, <th> elements should use scope, not headers, and should only appear when there is a single row and column of headers.
- Test the corrected table with a screen reader's table navigation mode to confirm each data cell is announced with its correct column/row header.
WooCommerce note
WooCommerce's default cart table template (templates/cart/cart.php) gives every column header cell in the table's thead row a scope="col" attribute (Remove item, Thumbnail image, Product, Price, Quantity, Subtotal), which satisfies this rule out of the box. If this issue appears on a cart, checkout, or custom order-history table, check for a theme override of that template, or a custom order-history/reports table, that dropped the scope attributes.
Before and after
Before
<table>
<tr>
<th>Order</th>
<th>Date</th>
<th>Status</th>
<th>Total</th>
</tr>
<tr>
<td>#1042</td>
<td>Aug 12, 2026</td>
<td>Shipped</td>
<td>$48.00</td>
</tr>
</table>
After
<table>
<tr>
<th scope="col">Order</th>
<th scope="col">Date</th>
<th scope="col">Status</th>
<th scope="col">Total</th>
</tr>
<tr>
<td>#1042</td>
<td>Aug 12, 2026</td>
<td>Shipped</td>
<td>$48.00</td>
</tr>
</table>