Concepts

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, alt attribute, aria-label, aria-labelledby, or computed text content.
  • Description — additional context. From aria-describedby or title attributes.
  • 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.