Accessibility & semantics

The `headers` attribute has quietly stopped earning its place

The `headers` attribute has quietly stopped earning its place

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> and scope on 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 headers attributes 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)

Related
Accessibility & semantics

Whether a dialog closes on outside click is a task question, not a style question

Adrian Roselli sorts modal close behaviour into three buckets — action required, no action required, and weird patterns — and argues you should pick a light-dismiss policy based on what the user came to do, not on how the dialog looks.

August 13, 2026
Accessibility & semantics

A primary-nav flyout built on `popover`, not `aria-expanded`

Adrian Roselli has rebuilt his 2019 disclosure-widget primary nav on the native HTML `popover` attribute. The rebuild is a clean map of what the platform now carries for you, and where you still need ARIA.

July 9, 2026
Accessibility & semantics

Chrome 150 hands composite-widget arrow keys to the browser

Chrome 150 ships the `focusgroup` HTML attribute, a way to get roving arrow-key focus inside composite widgets like listbox, tablist and toolbar without a line of JavaScript. Adrian Roselli has published script-free demos, and the spec story is still an Open-UI explainer.

July 6, 2026