Accessibility tree
Also: a11y tree, accessibility object model, AOM
The internal data structure browsers and operating systems build from the DOM, mapping every element to a role, name, state, and relationships — the data screen readers and other assistive technology actually traverse.
The accessibility tree is the operating-system-level data structure that screen readers and other assistive technologies actually consume. When you open a page in a browser, the browser builds two trees: the DOM tree (the regular HTML hierarchy) and the accessibility tree, a parallel structure derived from the DOM but containing accessibility metadata.
Understanding the accessibility tree explains roughly 80% of the otherwise-confusing behaviour of ARIA, screen readers, and “why isn’t this announcing?” debugging sessions.
What’s in it
Every node in the accessibility tree has:
- Role — what the element is: button, link, heading,
navigation, dialog. From the HTML element type or from explicit
ARIA
role="...". - Name — what the element is called. From label text,
altattribute,aria-label,aria-labelledby, or computed text content. - Description — additional context. From
aria-describedbyortitleattributes. - State — current state: pressed, expanded, checked, busy. From
HTML attributes (
disabled,required) or ARIA (aria-pressed,aria-expanded). - Properties — relationships and metadata:
aria-controls,aria-owns,aria-haspopup.
Screen readers walk this tree and announce each node based on these fields. Tab and arrow-key navigation routes through the tree, not the DOM.
Why purely-visual content vanishes
A <div onclick="...">styled to look like a button</div> has no role
in the accessibility tree — the browser sees a generic <div> and
records it as role="generic" (effectively invisible to assistive
tech). The onclick handler doesn’t move into the accessibility tree
because the accessibility tree only reflects what the browser
infers the element to be from its HTML role.
This is why semantic HTML matters at the most fundamental level: not because of style or convention, but because semantic HTML elements populate the accessibility tree with the right roles automatically. Non-semantic markup creates a div-soup tree that screen readers can’t make sense of.
ARIA’s job in the tree
ARIA exists specifically to populate the accessibility tree for cases
where native HTML doesn’t have a matching element. role="combobox"
tells the browser to put a combobox node in the tree for an element
that would otherwise have appeared as generic. aria-expanded="true"
sets a state property on that node.
ARIA does NOT change the DOM. It changes what the browser writes into the accessibility tree.
How to inspect it
Browser DevTools now expose the accessibility tree directly:
- Chrome / Edge DevTools — Elements panel → Accessibility tab (right column) shows the computed accessibility properties for the selected node. The “Full-page accessibility tree” toggle (Chrome flag in some versions) displays the tree as a sidebar.
- Firefox DevTools — Accessibility panel (icon in the toolbar) shows a dedicated accessibility-tree view, similar to the Elements view but rendered in accessibility-tree terms.
- Safari Web Inspector — Audit / Accessibility tab gives comparable inspection.
When you can see the accessibility tree, you can answer the question “why isn’t this announcing?” empirically. Almost always the answer is: the node in the accessibility tree has a different role than you thought, or its name is empty, or its state is wrong.
Why “accessibility tree” is the better mental model than “ARIA”
Engineers who learn ARIA without understanding the accessibility tree end up sprinkling ARIA attributes hoping screen readers will pick them up. Engineers who understand the accessibility tree know that ARIA’s job is to write specific fields into specific tree nodes, and that inspecting the tree directly is faster than guessing.