All rules

Sheath rule

a11y-table-headers

Tables must have proper header cells for accessibility.
Package
Core
Default severity
error by default
Auto-fix
Manual fix

#Why

Data tables need <th> elements to be accessible to screen readers. Headers help users understand the relationship between data cells and their column/row labels. Without headers, tables become difficult to navigate and understand.

#Examples

#Bad

<!-- Table without headers -->
<table>
<tr>
<td>Name</td>
<td>Email</td>
<td>Role</td>
</tr>
<tr>
<td>John</td>
<td>john@example.com</td>
<td>Admin</td>
</tr>
</table>

#Good

<!-- Table with header row -->
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>john@example.com</td>
<td>Admin</td>
</tr>
</tbody>
</table>
<!-- Table with scope for complex tables -->
<table>
<tr>
<th scope="col">Name</th>
<th scope="col">Email</th>
</tr>
<tr>
<th scope="row">John</th>
<td>john@example.com</td>
</tr>
</table>
<!-- Presentation table (layout only, no headers needed) -->
<table role="presentation">
<tr>
<td>Column 1</td>
<td>Column 2</td>
</tr>
</table>

#Options

Use these options to control header requirements and data-table detection.

Option Type Default Description
requireScope boolean false When true, <th> elements must have a scope attribute
minRows integer 2 Minimum static row count that makes a headerless table a data-table candidate
<?php
'a11y-table-headers' => ['error', [
'requireScope' => true,
'minRows' => 3,
]],

#Scope Values

Choose the scope value that describes the cells controlled by a header.

Value Use For
col Column headers
row Row headers
colgroup Headers spanning multiple columns
rowgroup Headers spanning multiple rows

When requireScope is enabled, a present static value must be one of these four keywords (case-insensitive). Empty and unknown values are reported; dynamic Blade scope values are left for runtime.

#Notes

  • Use role="presentation" or role="none" for layout tables (they won't be flagged)
  • Single-row tables are skipped (likely layout tables)
  • Use <thead>, <tbody>, and <tfoot> for additional structure
  • id and headers associate cells explicitly, for tables whose structure scope cannot describe
  • Tables, rows, and headers excluded by hidden, inert, or aria-hidden="true" do not contribute to the analysis
  • A conflicting none/presentation role on a focusable or globally named <th> is ignored by the browser, so the native header semantics remain
  • Conditional or dynamic accessibility-tree exclusion is not checked when its row and header outcomes cannot be determined

#References

#Related Rules