The `headers` attribute has quietly stopped earning its place
Marcus Osei
A screen-reader user landing in a data table needs one thing from you: the row and column a given cell belongs to, announced cleanly as they arrow around. The HTML headers attribute exists to make that link explicit — you put an id on a <th> and point each data cell at it — for the cases where a plain header/data relationship is not obvious enough on its own.
Adrian Roselli has just retested that mechanism against the current generation of screen readers and browsers, and the finding is short. Per his write-up, the headers attribute is largely useless.
What was tested, and against what
The retest was scoped to the headers attribute in HTML tables. Per Roselli, ARIA has no headers equivalent, so this is a question about the native HTML feature alone. He ran the pairings a Windows or macOS user is likely to sit in front of in 2026: Firefox 155 with NVDA 2026.2, Chrome 152 with JAWS 2026.2608.25, Edge 152 with Narrator on Windows 11 25H2, and Safari with VoiceOver on macOS 26.6.2. Mobile pairings were tested alongside.
The question was narrow. If you build a table with spanned or compound headers — the classic case the attribute was supposed to salvage — do those pairings announce the right thing when you add headers? And do they announce something worse when you leave it off?
The finding, unglamorous edition
Per Roselli, on desktop the screen-reader/browser pairings handle spanned header cells just as well without a headers attribute as with one, with a mild exception for Safari. On mobile, the pairings generally ignore row and column headers, spanned or not — the attribute has nothing to rescue there because the header announcements themselves are absent.
Those two lines are the whole story. The extra ids and headers values you were painstakingly wiring up buy you almost nothing that plain, honest table structure does not already give you.
Roselli's TL;DR is worth carrying into your review checklist: avoid spanning and compound headers given the inconsistent support, and treat the headers attribute as largely useless.
The real anti-pattern is the compound header, not the missing attribute
This is where the piece cuts against the reflex to reach for more markup. If a table needs headers to be legible, the header structure itself is usually trying to do too much — merged cells that straddle two categories, or a second visual row of subheaders that only makes sense next to the first.
The fix is not another attribute. The fix is fewer spans and more tables, or a genuinely rectangular one with <thead>, <tbody>, <th scope="col"> and <th scope="row"> doing their ordinary jobs. Every span you remove from a header row is one less inconsistency the pairings above have to guess at.
And on mobile the news is bleaker still. If the current pairings ignore row and column headers whether spanned or not, then a table whose meaning depends on a fancy header will read as a wall of numbers to a portion of your users. That is not a problem you can wire around with more id attributes.
For your next data table
- Prefer a plain, rectangular table with
<thead>,<tbody>andscopeon every header cell. Per the source, this is what current screen readers actually reflect back to their users. - Avoid spanning header cells and compound header rows. If a header needs two levels to be legible, split the content into two tables instead.
- Do not add
headersattributes as insurance. The retest shows they do not pay for the effort of maintaining them, and they will not save a table whose structure is already fighting the reader. - On mobile, assume the header will not be announced at all, and do not design a table whose meaning depends on it.
The platform gave you <table>, <th> and scope for this job, and current assistive tech reads them cleanly. That is the tool. Reach for it first, and let headers retire quietly.
Source: Adrian Roselli (adrianroselli.com)