👀 Live Preview
Simple table with headers linking data cells to column header ids:
| Name | Score |
|---|---|
| Alice | 92 |
| Bob | 87 |

The headers attribute links table data cells to their header cells using space-separated id values. Screen readers use these associations to announce which row and column headers apply to each cell—especially important in complex tables with merged cells or multi-level headers.
Reference th id values.
Where headers applies.
Multiple ids allowed.
rowspan and colspan.
When to use each.
cell.headers property.
headers AttributeThe headers attribute is used on <td> and <th> elements to explicitly associate a cell with one or more header cells. Each referenced header must have a unique id attribute. This helps assistive technologies understand the relationship between data and the labels that describe it.
In simple tables with a single row of column headers and a single column of row headers, the scope attribute on <th> is often sufficient. The headers attribute becomes essential when scope alone cannot express the relationships—for example, when headers span multiple rows or columns with rowspan and colspan.
The headers attribute has no visual effect. It exists purely to improve how screen readers announce table content. Always pair it with semantic structure: <thead>, <tbody>, and a descriptive <caption>.
Add headers to a <td> or <th> with a space-separated list of header cell id values:
<table>
<thead>
<tr>
<th id="name" scope="col">Name</th>
<th id="score" scope="col">Score</th>
</tr>
</thead>
<tbody>
<tr>
<td headers="name">Alice</td>
<td headers="score">92</td>
</tr>
</tbody>
</table><td> and <th> elements inside a table.id values from header cells (<th>).id must be unique within the document.scope on <th> is often enough; use headers when relationships are ambiguous.The headers attribute accepts one or more header cell id values, separated by spaces:
headers="name" — Associates the cell with a single column or row header.headers="north q1 q1-sales" — Associates a cell with multiple headers: a row header, a group header, and a sub-header.headers="region q2-units" — Common in sales or financial tables with nested column groups.<!-- Single header reference -->
<td headers="product">Widget A</td>
<!-- Multiple header references -->
<td headers="west q3 q3-revenue">$48,200</td>| Concept | Details | Notes |
|---|---|---|
| Applies to | <td>, <th> | Table cells only |
| Value format | Space-separated id list | e.g. "row1 col2" |
| Header requirement | Referenced cells need id | Each id must be unique |
| Simple tables | scope on <th> | Often sufficient alone |
| Complex tables | headers on data cells | Needed with rowspan/colspan |
| JS property | cell.headers | String of space-separated ids |
| Element | Supported? | Notes |
|---|---|---|
<td> | Yes | Primary use — link data cells to headers |
<th> | Yes | Sub-headers in complex layouts may reference parent headers |
<table> | No | Set headers on individual cells |
<div>, <span> | No | Table-cell attribute only |
scope vs headers| Approach | Example | When to Use |
|---|---|---|
scope="col" | <th scope="col">Name</th> | Simple tables with one header row |
scope="row" | <th scope="row">Total</th> | Simple row header labels |
headers="id1 id2" | <td headers="region q1-sales"> | Complex tables with merged or nested headers |
| Combined | scope + headers | Best practice for large accessible tables |
Basic header association, a multi-level sales table with rowspan and colspan, and dynamic headers with JavaScript.
Simple table with headers linking data cells to column header ids:
| Name | Score |
|---|---|
| Alice | 92 |
| Bob | 87 |
Here’s a straightforward table using <thead>, <tbody>, and headers to link each data cell to its column header:
<table>
<caption>Student Scores</caption>
<thead>
<tr>
<th id="name" scope="col">Name</th>
<th id="score" scope="col">Score</th>
</tr>
</thead>
<tbody>
<tr>
<td headers="name">Alice</td>
<td headers="score">92</td>
</tr>
<tr>
<td headers="name">Bob</td>
<td headers="score">87</td>
</tr>
</tbody>
</table>Each <th> has a unique id. Data cells use headers to point at the matching header id. Even though scope="col" already helps in this simple layout, explicit headers references reinforce the association for assistive technology.
When headers span rows and columns, scope alone may not be enough. Use headers to link each data cell to all relevant labels:
<table>
<caption>Quarterly Sales by Region</caption>
<thead>
<tr>
<th id="region" rowspan="2">Region</th>
<th id="q1" colspan="2">Q1</th>
<th id="q2" colspan="2">Q2</th>
</tr>
<tr>
<th id="q1-sales" headers="q1">Sales</th>
<th id="q1-units" headers="q1">Units</th>
<th id="q2-sales" headers="q2">Sales</th>
<th id="q2-units" headers="q2">Units</th>
</tr>
</thead>
<tbody>
<tr>
<th id="north" scope="row">North</th>
<td headers="north q1 q1-sales">$12,400</td>
<td headers="north q1 q1-units">310</td>
<td headers="north q2 q2-sales">$14,800</td>
<td headers="north q2 q2-units">370</td>
</tr>
<tr>
<th id="south" scope="row">South</th>
<td headers="south q1 q1-sales">$9,600</td>
<td headers="south q1 q1-units">240</td>
<td headers="south q2 q2-sales">$11,200</td>
<td headers="south q2 q2-units">280</td>
</tr>
</tbody>
</table>The Q1 and Q2 group headers use colspan, and sub-headers reference them with headers="q1". Data cells list all three relevant ids—row, group, and sub-header—so screen readers can announce the full context, such as “North, Q1, Sales: $12,400.”
You can set or update the headers attribute at runtime when table structure changes dynamically:
<table>
<tr>
<th id="headerId">Revenue</th>
</tr>
<tr>
<td id="dataCell">$5,000</td>
</tr>
</table>
<script>
var cell = document.getElementById("dataCell");
cell.headers = "headerId";
// or: cell.setAttribute("headers", "id1 id2");
</script>The script assigns the header id to the data cell at runtime. This is useful when rows or columns are added dynamically and you need to maintain correct header associations without rewriting the entire table markup.
id — Referenced ids must exist and be unique within the page.headers for complex layouts — When rowspan, colspan, or nested headers break simple scope relationships.<caption> — Summarize the table purpose before users navigate individual cells.<thead> and data rows in <tbody>.headers references.Each th gets a unique id attribute.
headers lists space-separated id values.
Cell-to-header relationships exposed to AT.
Screen readers announce full header context.
The headers attribute is fully supported in all modern browsers on <td> and <th> elements. Correct markup matters more than browser quirks—assistive technology depends on valid id references.
All major browsers expose headers in the accessibility tree for table cells.
Bottom line: Use headers confidently for complex tables; validate with a screen reader to confirm associations.
id values to every header cellheaders when rowspan or colspan breaks simple scope<caption> on data tablesscope and headers in large tablesheaders in complex multi-level layoutsThe headers attribute is a powerful accessibility tool for HTML tables. By linking data cells to their header cells through space-separated id references, you help screen reader users understand complex tabular data with confidence.
For simple tables, scope on <th> may be enough. When your layout uses merged cells or nested headers, headers fills the gap that scope alone cannot cover. Always validate your work with assistive technology.
headersBookmark these before building accessible tables.
Space-separated list.
SyntaxCell attribute.
Scoperowspan/colspan.
A11ySet in JavaScript.
Scriptheaders when needed.
Patternid values. Screen readers use these associations to announce which row and column headers apply to each cell.<td> and <th> elements inside a table. Referenced header cells must have matching id attributes.scope on <th> declares row or column direction and works well for simple tables. headers explicitly lists header ids and is needed when relationships are ambiguous due to merged cells.headers when a data cell belongs to multiple headers—for example, a sales figure tied to both a region row and a quarter column in a table with rowspan or colspan.cell.headers = "headerId" or cell.setAttribute("headers", "id1 id2") with a space-separated list of header ids.headers attribute. Focus on correct id references and table structure for reliable assistive technology behavior.Practice the headers attribute with basic and complex table examples in the Try It editor.
4 people found this page helpful