A quick note before we begin:
The “End-to-end browser and accessibility event architecture” article, along with the architectural diagram, describe all the systems that exist inside the browser, accessibility pipeline, and assistive technologies. It’s a map of the components.
This article is different — it shows the processes that flow through those systems when a user clicks an accordion button.
These flows are not linear. Events jump between multiple layers (JavaScript, Web APIs, rendering, accessibility trees, OS APIs, and assistive technologies).
That’s simply how the architecture works: it is an intricate, concurrent set of systems that constantly talk to each other.
So don’t expect a neat step-by-step “path” — expect a dance that moves across different layers.
An accordion button
Imagine a screen reader user encounters a button used to toggle an accordion open and closed.
In the closed state, the markup will be:
<button aria-label="Open accordion" aria-expanded="false">
</button>
When the button is triggered, the markup will change to:
<button aria-label="Open accordion" aria-expanded="true">
</button>
This is important as the button will then be announced as either “collapsed” or “expanded”.
How the accordion is toggled
In this example, a small piece of JavaScript is attached to the button. When the user clicks it, an event handler runs.
This code listens for the click and updates the DOM by toggling aria-expanded between "false" and "true".
The browser will run this script later in the flow.
Let’s review the entire process from start to finish.
The process
1. User interacts with the button
The browser begins with the HTML and ARIA shown above, which define the button’s role, name and state.
- Name: Open accordion
- Role: button
- State:
aria-expanded="false"(which screen readers announce as “collapsed”).
The button has just been clicked!
No JavaScript runs yet — the browser simply has a semantic, labelled button, which sets the foundation for everything that follows.
2. Browser computes the click target and synthesises a click event
The operating system sends low-level input events — such as pointerdown, mouseup, or pointermove — to the browser.
The browser performs hit-testing 1 to determine which on-screen element was targeted.
Based on this sequence of low-level events, the browser synthesises a DOM click event so it has a standard way to represent the interaction.
The event object contains information such as event type, target element, coordinates, and whether the event should bubble 2.
3. The click event enters the task queue
The browser does not run your script immediately.
Instead, it schedules a “dispatch click event” task 3 and places it into the Task Queue 4.
The task will run when the JavaScript engine is idle and ready for the next piece of work.
4. The event loop hands the click task to the JavaScript engine
When the event loop 5 is ready for a new task, it selects the “dispatch click event” task and hands it to the JavaScript engine.
5. The event handler runs
The browser’s event dispatch algorithm determines which element should receive the event.
The browser then runs any event listeners on that element and its ancestors. Your event handler runs and updates the DOM — in this case, toggling aria-expanded="true".
This DOM mutation 6 may cause style recalculation or layout updates.
When the handler finishes, JavaScript execution ends and control returns to the browser.
6. Browser updates style, layout, or paint if needed
The browser may update style, layout, or paint after the DOM change — either immediately or during the next rendering phase.
This may involve recalculating styles, updating layout, and repainting changes on screen.
Note: These updates do not always happen immediately. The browser may batch, defer, or skip work depending on performance optimisations.
7. Browser updates the accessibility tree
The browser updates its internal AXTree (accessibility tree) to reflect the button’s new state.
This includes recomputing accessibility properties — such as name, role, and the updated aria-expanded="true" value.
Note: AXTree updates can occur during or shortly after DOM and layout updates, depending on the engine’s scheduling.
8. Browser fires accessibility events
The accessibility subsystem determines what changed and generates one or more AXEvents — internal accessibility notifications such as “expanded state changed”.
These AXEvents are delivered through the operating system’s accessibility API.
9. Events cross the OS accessibility API boundary
The browser sends these AXEvents to the operating system’s accessibility API, such as:
- AX API on macOS and iOS
- UIA on Windows
- ATK and AT-SPI on Linux
The OS accessibility API notifies assistive technologies, which may also request additional information from the browser.
10. Screen reader receives events and queues utterances
The screen reader gets the notification. It then decides what to announce based on user settings.
The message is added to its internal speech queue 7. This queue manages things like order, interruptions, and priority.
It then outputs speech or braille.
The user hears: “Open accordion. Expanded.”
The process is now complete.
Caveats and nuances
- This a broad generalisation of how browsers work.
- Internals may differ across different browsers
- Screen readers may differ in how they interpret events and generate speech.
- Many steps happen automatically and are not visible to developers.
- The final behaviour may depend on a range of factors including: browser, OS, assistive tech, and user settings.
Footnotes
- [1] Hit-testing: The browser’s method for locating which on-screen element sits under the user’s tap, click, or pointer position. [Back]
- [2] Bubble: When a DOM event happens on an element, it “bubbles up” the page — first the element, then its parent, then its parent’s parent. [Back]
- [3] Dispatch click event task: A scheduled piece of work telling the browser: “run this element’s click event when the JS engine is ready.” [Back]
- [4] Task Queue: A queue where the browser stores tasks like user events, timers, and network callbacks until the event loop selects them. [Back]
- [5] Event loop: The mechanism that selects and runs tasks and microtasks, and yields control to the browser between them. [Back]
- [6] DOM mutation: Any change to the DOM tree. These mutations can occur with or without JavaScript. [Back]
- [7] Internal speech queue: A screen reader’s ordered list of messages waiting to be spoken, used to manage timing and interruptions. [Back]