Max Design

Published:

Note: The following steps show my understanding of how Chrome builds its accessibility tree, based on Chromium’s open-source code. Source references are listed at the end.

We’re often told that the browser builds its accessibility tree ‘from the DOM,’ but what does that actually involve?

Let’s look at how Chrome builds its accessibility tree, from start to finish.

1. Identify which DOM nodes are “interesting” for accessibility

Chrome walks the DOM and filters out anything that has no semantic or interactive value — such as hidden elements, inert content, non-semantic containers, and visual-only wrappers.

2. Compute the AXRole for each element

Blink works out the accessibility role using native HTML first, then ARIA, with a fallback if the ARIA role cannot be used.

3. Compute the Accessible Name + Description

Chrome runs the full Accessible Name and Description Computation algorithm using aria-labelledby, aria-label, native naming rules, and text content.

4. Build the AXNode for this DOM node

For every exposed element, Blink creates an AXNode containing its role, name, description, states, value, and other accessibility metadata.

5. Build the AX Tree Hierarchy (Parent/Child Relationships)

Chrome builds parent and child relationships using the DOM structure, ARIA such as aria-owns, and extra nodes created for some controls such as lists, tables and form elements.

6. Compute Relationships

Blink connects related accessibility information, including aria-labelledby, aria-describedby, aria-controls, aria-activedescendant, and table relationships.

7. Compute States and Properties

Chrome works out states such as focus, checked, expanded, disabled, busy, required and selected, and adds any relevant ARIA states and properties.

8. Compute Bounding Boxes + Layout-dependent attributes

Chrome works out the onscreen position and size of each accessibility node. This helps assistive technology find and move between elements on the page.

9. Finalise the AXTree snapshot

Blink builds a stable version of the accessibility tree, stores calculated values, and tracks which nodes have changed.

Note: This “what changed?” information is crucial. Blink uses it to decide whether an accessibility event needs to be sent. It is the differences between the old and new snapshots that trigger accessibility events.

10. Generate AXEvents based on tree changes

Chrome compares the old and new accessibility data, then sends events when something important has changed, such as a name, value, focus or live region.

11. Deliver the AXTree + AXEvents to the OS Accessibility API

Blink maps its internal accessibility nodes to the platform accessibility API, such as AX API, UIA or AT-SPI, and updates the accessibility tree.

12. OS API delivers events → Assistive Technology receives them

The operating system hands these events to the screen reader, which then interprets them and decides what, and when to speak.

And all of this happens in the blink of an eye (pun intended).

Modern browsers run through all these steps continuously, incrementally, and with a lot of optimisation. This often within microseconds!


Sources

Blink Accessibility Core: ax_object.cc

What it covers:

AX Tree Serialization: ax_tree_serializer.h

What it covers:

AXNode Structure: ax_node.h

What it covers: