Table cells using the headers attribute must reference existing cells
Estimated effort: about 10 minutes.
Some data tables link each cell to its header using a headers attribute that lists the id(s) of the relevant header cell(s), instead of using the simpler scope attribute. If a headers attribute references an id that doesn't exist anywhere in the table (a typo, or a header cell that was later removed), a screen reader can no longer announce that column/row's header when reading the cell, which is especially disorienting on a long order-history or order-detail table with many similar-looking numeric columns.
How to fix it
- Find <td> (or <th>) elements that use a headers="..." attribute, commonly seen in complex order-history or order-detail tables with merged or multi-level headers.
- For each id listed in a headers attribute, confirm that a <th> element with that exact id exists somewhere in the same table.
- Fix any mismatch by correcting the typo'd id, or by removing the stale reference if the corresponding header cell no longer exists.
- For most simple e-commerce tables (a cart table, a single order's line items), a scope="col"/scope="row" attribute on each <th> is simpler and sufficient — consider switching to scope instead of headers/id pairs unless the table genuinely has complex, multi-level headers that scope cannot express.
- Re-check the table with a screen reader's table navigation mode to confirm each data cell announces the correct header text.
WooCommerce note
WooCommerce's default cart table template (templates/cart/cart.php) uses scope="col" on each <th> in the table header row rather than the headers/id attribute pattern that this rule checks, so a fresh, unmodified WooCommerce cart table will not trigger this rule. If it appears on a cart, checkout, or order-history table, look for a theme override or a custom order-history/reports table that introduced its own headers/id markup.
Before and after
Before
<table>
<tr>
<th id="order-date">Order Date</th>
<th id="order-total">Total</th>
</tr>
<tr>
<td headers="order-date-x">Aug 12, 2026</td>
<td headers="order-total">$48.00</td>
</tr>
</table>
After
<table>
<tr>
<th id="order-date">Order Date</th>
<th id="order-total">Total</th>
</tr>
<tr>
<td headers="order-date">Aug 12, 2026</td>
<td headers="order-total">$48.00</td>
</tr>
</table>