Skip to content
Accessibility Lab · LAB-08accessibility tree / role

The invisible DOM

There are two trees. You wrote one of them. Assistive technology reads the other.

Level
ENGINEER
Read time
10 min
Experiment
Available
Type
INTERACTIVE

The question

A div with a click handler looks and behaves like a button on screen. What exactly is missing, and where does that difference live?

Hypothesis

The browser derives an accessibility tree from the DOM. Native elements contribute a role, a name, states and built-in keyboard behaviour; a styled div contributes a generic node with none of those.

Method

Laboratory available

The instrument for this investigation runs in the laboratory, where the controls, the live model and the observation log share one workstation.

Enter the laboratory

Edit the markup on the left. The accessibility tree on the right is recomputed with the role, accessible name and state that assistive technology would actually receive.

What we observed

Capability<button><div onclick>
Role announcedbuttongeneric
Reachable by Tabyesno (needs tabindex="0")
Enter and Space activate ityesno (needs a keydown handler)
Disabled state honouredyesno
Participates in a formyesno
Exposed to voice control by nameyesonly with an explicit name
Shows in the browser's find-and-click toolingyesunreliable
What a native control gives you for free

Why it happens

example.htmlhtml
<!-- Correct: role, focus, keyboard, disabled all included --><button type="button" onclick="save()">Save</button><!-- Recoverable, but you now own the keyboard contract --><div role="button" tabindex="0" onclick="save()" onkeydown="if (event.key === 'Enter' || event.key === ' ') save()">Save</div><!-- Invisible to keyboard and assistive technology --><div class="btn" onclick="save()">Save</div>
The same control, three ways

Visual hiding has three distinct meanings and people routinely pick the wrong one. display: none and visibility: hidden remove the node from the accessibility tree. opacity: 0 and clip-path do not, the content stays announced and focusable, which is how invisible focus traps happen. A visually-hidden utility class is the correct tool for text intended only for screen readers.

example.csscss
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;}
The standard visually-hidden utility

Further research

The accessibility tree is not a copy of the DOM. Presentational nodes are pruned, anonymous boxes are ignored, and generated content may or may not appear. Browsers expose it through platform APIs. UIA on Windows, AX on macOS, AT-SPI on Linux, so two browsers can legitimately expose the same markup slightly differently. Chrome DevTools, Firefox's Accessibility panel and Safari's Audit tab all let you read the computed tree directly.

References

  1. 01W3C, accnameAccessible name and description computation
  2. 02W3CARIA Authoring Practices Guide
  3. 03MDNThe accessibility tree