Most accessibility specialists understand HTML, ARIA, and assistive technologies at a surface level, but the layers between them are often a mystery.
When announcements behave unexpectedly or different browsers produce different results, the cause usually lies in these hidden systems.
This diagram maps that entire path and shows how user input, JavaScript, layout, accessibility events, and assistive technology output move through the browser in sequence.
Understanding these layers could help you interpret screen reader behaviour, explain browser differences, and troubleshoot issues that cannot be solved at the HTML level alone.
How to read this diagram
The diagram shows the architecture of the browser, not a strict top-to-bottom sequence of steps.
Each box represents a layer or component that the browser may use during an interaction, but the browser does not move through these boxes in numerical order.
When something happens — like a click, a focus change, or a live-region update — the browser jumps between these layers as needed:
- the event loop runs many times
- the JavaScript engine is entered and exited
- microtasks run inside the same turn
- rendering happens only when something visually changes
- the accessibility tree updates whenever the browser’s accessibility subsystem detects relevant DOM or layout changes — not strictly after rendering.
- the screen reader responds when AX events arrive
So the diagram is a map of the system, not a timeline.
Let’s look at each section of the diagram.
Table of contents
- Developer-facing layer (input)
- Browser engine layer (transformation)
- JavaScript engine
- Browser APIs (Web APIs)
- Microtask queue
- Task queue
- Event loop
- OS Accessibility API interface
- Assistive technology layer (interpretation)
Developer-facing layer (input)
This layer includes HTML, ARIA 1 and some DOM 2 features. Browsers use this information to determine the role of each element, how they behave, and how they should be exposed to assistive technologies.
Key structures in this layer
HTML semantics
These are the built-in meanings of HTML elements such as <button>, <nav>, and <h1>. Semantics help the browser understand the structure and purpose of each part of a page.
They also guide default behaviours, such as whether elements receive focus, how keyboard interaction works, and how an element should be exposed in the accessibility tree.
ARIA attributes
ARIA is a set of custom HTML attributes that add information to the accessibility tree to help assistive technologies.
DOM Focus API
This API 3 lets developers control how keyboard focus works. This is important for accessibility because assistive technologies rely on focus being managed in meaningful and intuitive ways.
DOM and accessibility computation interfaces
These interfaces provide inputs for the accessibility pipeline, which ultimately computes the final values exposed to assistive technologies.
They determine what assistive technologies will receive through the accessibility tree. This category also includes newer capabilities, such as ElementInternals 4, which allows custom elements to expose proper semantics without relying on ARIA.
Key processes in this layer
HTML parsing
The browser reads raw HTML and begins turning it into DOM nodes, applying default semantics and element roles.
ARIA attribute resolution
ARIA attributes are collected and associated with their elements so they are available during later accessibility computations.
Accessible name and description computation
The browser applies the Accessible Name and Description Computation algorithm to determine the element’s name from text, attributes or references.
Role and state mapping
Native semantics and ARIA overrides are mapped to internal accessibility concepts such as “button,” “checkbox,” “expanded,” or “disabled.”
Focus model normalisation
The browser applies focus rules based on element type, tabindex and special interactions (e.g. click-to-focus behaviour for buttons).
Browser engine layer (transformation)
This is where the browser converts HTML and CSS into internal structures it can work with. It builds the DOM, CSSOM, and layout tree.
These trees represent the page’s structure, its styling, and its visual layout. Everything else in the browser depends on these structures.
Key structures in this layer
DOM tree
The DOM tree is the browser’s internal model of the HTML document. It is a structured representation made of elements and text nodes 5.
JavaScript uses this tree to read content, modify attributes, insert or remove elements, and respond to user actions. All interaction and accessibility behaviour begins with the DOM.
CSSOM tree
The CSSOM tree is the browser’s internal model of all CSS rules, declarations, and computed styles. This tree is used to determine how each element is presented on-screen.
Layout tree
The layout tree (sometimes called the frame tree or render tree, depending on engine) combines information from the DOM and CSSOM and determines where each element appears to create the final layout.
Key processes in this layer
Parsing → DOM and CSSOM construction
HTML becomes DOM nodes; CSS becomes the CSSOM. These structures power layout, rendering and scripting.
Style calculation
The browser resolves which CSS rules apply to every element, calculating final values such as colours, font sizes and display types.
Layout (or “reflow”)
The engine computes geometry: sizes, positions, constraints and relationships across the entire page (or just the affected subtree).
Hit-testing
The browser looks at the rendered layout to determine which element sits under a specific screen coordinate (e.g. finger or mouse).
Painting
Each visual element is converted into drawing commands: backgrounds, borders, text, images, shadows, etc.
Compositing
The browser builds layers, resolves stacking contexts, and produces the final rendered frame shown on screen.
Accessibility tree synchronisation
Changes in the DOM or layout trigger updates in the internal accessibility tree, ensuring names, roles, and states reflect the current UI.
JavaScript engine
This is where JavaScript code runs. It keeps track of which functions are currently executing in the call stack and stores objects and data in the heap. The JS engine runs only when the event loop hands it a task.
Key structures in this layer
Call stack
The call stack is a structured list that tracks which JavaScript functions are currently running.
When functions are called, they are pushed onto the call stack. When finishes, they are "popped off". The browser can only run one piece of JavaScript at a time because only one function can sit at the top of the call stack. This ordered execution is essential for predictable behaviour.
Note: The JavaScript call stack is not a place where events or tasks are stored. It is a temporary execution structure created by the JS engine while code is running. When the engine is idle, the call stack is empty and effectively does not exist.
Heap
The heap is an area of memory that holds data that JavaScript can access and update as needed.
Key processes in this layer
Execution context creation
Whenever code runs (an event handler, a script block, a callback), a fresh execution context is created.
Call stack construction
As functions call other functions, stack frames are pushed; as they return, frames are popped. The stack only exists while JS is running.
Event dispatch algorithm
When the browser delivers an event, it runs capture → target → bubble phases and invokes the relevant listeners.
Microtask checkpoint
After each task, all queued microtasks (e.g. Promises 6) are run before the browser proceeds.
Garbage collection
Unused memory is reclaimed to keep the engine efficient and prevent leaks.
Browser APIs (Web APIs)
These are the features the browser exposes to JavaScript, such as timers, networking, DOM manipulation, storage, and geolocation.
They allow JavaScript to interact with the outside world, but the work they perform happens outside the JavaScript engine.
When JavaScript runs, synchronous code executes immediately on the call stack. But asynchronous operations—such as timers, Promises, network requests, and DOM events—are handled by Web APIs, which schedule their callbacks into either the task queue or the microtask queue.
The event loop selects the next task and instructs the JavaScript engine to run it. As the engine runs the task, it creates the call stack and executes the code one step at a time.
Key processes in this layer
Task scheduling
setTimeout 7, setInterval 8, postMessage 9 and user events create tasks that will eventually be placed in the Task Queue.
Microtask scheduling
Promise.then 10, queueMicrotask 11, and MutationObserver 12 notifications create microtasks to be run at microtask checkpoints.
Network and file I/O callbacks
Fetch/XHR 13, WebSockets 14 and File operations schedule tasks when data arrives or operations finish.
Animation scheduling
requestAnimationFrame 15 registers callbacks to be delivered at the next vsync-aligned animation frame, after the rendering pipeline signals a frame opportunity.
Mutation observation
DOM mutations 16 trigger MutationObserver records, queued for delivery as microtasks.
Microtask queue
This queue contains small, high-priority jobs that run immediately after the current JavaScript block finishes and before the browser updates the screen.
Promises and some callback types are added here.
The microtask queue helps the browser complete quick follow-up work efficiently. Heavy microtask churn delays JavaScript yielding, which can delay rAF callback delivery and some accessibility event dispatch.
Key processes in this layer
Promise reaction processing
When a Promise resolves or rejects, its .then/.catch 17 handlers are queued as microtasks.
MutationObserver delivery
DOM mutation records are delivered as microtasks after the task that caused them finishes.
Cleanup operations
FinalizationRegistry 18 and other engine-managed clean-up tasks run as microtasks.
Checkpoint execution
All microtasks must run to completion before the browser can render or pick up another task.
Task queue
This queue holds larger, scheduled jobs such as user interaction events, timers, network responses, and postMessage callbacks. Tasks run one at a time, in order, and each task waits for its turn.
Most JavaScript responding to clicks, keypresses, or DOM updates is delivered through tasks, which means accessibility-related logic also depends on task timing. This structured sequencing keeps browser behaviour predictable and avoids race conditions.
After tasks, the browser may schedule layout or accessibility updates, depending on invalidation state — these are not guaranteed to run immediately.
Key processes in this layer
User interaction task creation
Events such as clicks, key presses or touches place interaction tasks into the queue.
Network/task callbacks
Network responses, timers, and messaging APIs add new tasks to the queue.
Task selection
Each browser picks tasks according to its scheduling rules, interaction priority and fairness guarantees.
Yielding conditions
Tasks only execute when no JavaScript is running and the event loop is ready.
Event loop
The JavaScript event loop coordinates JavaScript task scheduling, not the entire browser. It is responsible for:
- executing queued JavaScript tasks (e.g. event handlers, timers, network callbacks)
- running microtasks (Promises, MutationObservers)
- delivering requestAnimationFrame callbacks after the rendering pipeline signals a new frame opportunity
However, the JS event loop is not the browser’s master scheduler. Major subsystems operate independently, often on their own threads or processes:
- layout, paint, and compositing (rendering)
- the compositor and GPU pipeline
- networking
- input handling
- the accessibility subsystem (AX tree updates + AXEvents)
These systems run whether or not JavaScript is executing, and many can continue even while the main thread is blocked.
What the JS event loop actually controls
- the ordering of JavaScript tasks
- the ordering and draining of microtasks
- when JavaScript yields control back to the browser
- when rAF callbacks run after the rendering pipeline signals a vsync-aligned render tick
What the JS event loop does not control
- rendering or compositing
- accessibility tree updates or AXEvent dispatch
- networking
- GPU work
- input processing
- any thread other than the main JS thread
Event loop cycle
- Run the next JavaScript task.
- Drain the microtask queue completely.
- Yield to the browser. At this point, independent subsystems may run:
- rendering pipeline (layout → paint → composite), usually driven by vsync
- accessibility-tree updates and AXEvents
- input processing
- network progress
- If the rendering pipeline signals a frame opportunity, queue and run rAF callbacks before the next task.
- Sleep until the next ready task or callback.
OS Accessibility API interface
This part of the browser builds and updates the accessibility tree, generates accessibility events such as focus changes and live region updates, and passes them to the operating system’s accessibility API.
It ensures that assistive technologies always have an accurate and up-to-date view of the web page.
Assistive technologies do not constantly query the accessibility tree. Instead, they rely mainly on AXEvents to know when something meaningful has changed.
Key structures in this layer
AXTree
The AXTree is the browser’s dedicated accessibility tree. It is not a direct copy of the DOM. Some DOM nodes are ignored, others are merged or split into multiple accessibility nodes, depending on semantics and platform rules.
The AXTree is a specialised representation of the page that focuses on semantic meaning rather than visual layout. Each node in the tree exposes information such as roles, accessible names, descriptions, states, and relationships.
Assistive technologies depend on this structure to understand what is on the page and how users can interact with it.
AXEvents
AXEvents are notifications the browser sends whenever something changes that is relevant to accessibility. Examples include focus moving to a new element, text updates in a live region, changes in an element’s value, or updates to states such as expanded or disabled.
These events allow assistive technologies to react in real time and keep users informed of important changes.
OS accessibility API interface
This is the layer where the browser hands off accessibility information to the operating system’s accessibility API, such as UIA on Windows 19, AX API on macOS and iOS 20, or ATK and AT-SPI on Linux 21.
The operating system exposes this information to assistive technologies, which read and interpret the page based on the data the browser provides.
Key processes in this layer
AXTree construction
The browser maps DOM elements to accessibility objects with names, roles and states.
AXTree diffing
When something changes, the browser compares the previous AXTree state with the new one.
AXEvent generation
Based on the diff, the browser fires events such as “name changed,” “state changed,” “focus changed,” “value changed.”
Live region detection
ARIA live regions trigger AX events when their accessible text changes.
Relationship remapping
ARIA attributes such as aria-owns, aria-labelledby and aria-controls can change how objects relate in the AX tree.
OS API mapping
The browser converts internal AX objects into the structures and notifications required by the OS API.
Object exposure
The browser exposes AX nodes as OS-native accessibility objects (UIA, AX API, AT-SPI).
Notification delivery
The OS receives events from the browser and forwards them to assistive technologies.
Value/state propagation
When roles, states or values change, the OS updates its version of the accessibility object.
Event coalescing
APIs may merge related events to avoid flooding ATs with redundant notifications.
AT registration
Screen readers subscribe to receive events for active UI elements.
Assistive technology layer (interpretation)
This layer is where assistive technologies operate. They interpret all of the information and use this to generate speech or braille output. They also send user information back to the browser.
Before assistive technologies can present information or send user commands back to the browser, they run through several internal steps that interpret events, apply preferences, and manage output.
Key structures in this layer
AT client
The AT client is the assistive technology program, such as NVDA, JAWS, VoiceOver, Orca, or TalkBack.
AX event interpreter
The AX event interpreter listens for incoming accessibility events and decides how to respond. It determines whether something should be spoken, updated in braille, added to a queue, or ignored based on context and user settings. This interpreter is central to how AT remains responsive without overwhelming the user.
Speech queue (utterances)
The speech queue holds spoken messages before they are passed to the text-to-speech engine. It allows the AT to manage competing announcements, decide what should interrupt or replace previous speech, and present information in the correct order.
Braille display output buffer
The braille output buffer holds the formatted text, cursor position, and structural indicators that will appear on a refreshable braille display. It manages updates efficiently so changes are reflected without disrupting the user’s reading flow.
TTS engine
The text-to-speech (TTS) engine converts text into spoken output using the chosen synthesized voice.
Braille output engine
The braille output engine sends text and formatting instructions to the physical braille display. It ensures that contractions, cursor routing, and display updates match the user’s braille preferences.
User input router
The user input router receives keyboard shortcuts, braille input, gestures, and touch commands from the user. It translates these into the correct instructions for the browser, such as moving focus, activating elements, or performing navigation commands.
User settings
User settings shape how the assistive technology behaves. These include speech rate, punctuation level, verbosity, braille grade, typing mode, navigation mode, and many other preferences. These settings influence what is announced, how quickly it is spoken, and how information is presented.
Key processes in this layer
Event routing
The screen reader receives OS accessibility events and determines what they signify.
Speech queue management
The screen reader adds announcements to its internal speech queue and decides how to prioritise, interrupt, merge or flush them. Assertive announcements may jump to the front, while polite announcements wait their turn unless settings or context change that behaviour.
Interruption rules
Assertive updates may interrupt the queue; polite updates may wait.
Braille buffer updates
Changes to state or focus update the braille display’s live buffer.
User setting checks
Verbosity, punctuation, typing echo and other user preferences shape how the event is presented.
Output rendering
Speech is spoken via TTS; braille is displayed on refreshable hardware
Conclusion
Understanding this full pipeline gives accessibility specialists a clearer view of why things work the way they do.
It shows how user actions, code, rendering, and accessibility events move through the system, and how timing or browser differences can influence what assistive technologies announce.
By seeing the complete journey of an event, we can diagnose issues more accurately, predict behaviour more confidently, and create more reliable and accessible user experiences.
Caveats and nuances
This model is conceptual, not a literal browser implementation
Each browser engine structures its internal pipelines differently. The diagram simplifies these systems to highlight their relationships, not to mirror every engine’s exact architecture.
Browser engines do not behave identically
Blink, WebKit and Gecko differ in how they build layout trees, fire accessibility events, schedule tasks and expose information to OS accessibility APIs. Timing and order can vary across engines and versions.
AXTree creation rules are implementation-dependent
Browsers may merge, omit or create additional accessibility nodes based on platform heuristics. The details differ across operating systems and are not fully standardised.
Accessibility event timing is not guaranteed
Browsers may batch, coalesce or defer AXEvents depending on workload, rendering state or optimisation strategies. Real-world timing can differ from the general flow described in the article.
Screen readers interpret events differently
ATs have their own rules for queuing, interrupting and presenting announcements. Their responses depend on version, settings, OS behaviour and internal heuristics.
JavaScript scheduling can affect accessibility timing
Long tasks, microtask pressure and main-thread blocking can delay rendering or AXEvents. Frameworks that heavily use Promises or MutationObserver may influence announcement order.
OS accessibility APIs apply their own semantics
UIA, AX API and AT-SPI each impose platform-specific rules for roles, states, relationships and event types. Screen readers see this OS-level interpretation, not the raw browser data.
Rendering stages may not follow a fixed order
Layout, paint and compositing steps can be deferred, skipped or merged depending on workload, throttling, animations or visibility. This affects when the accessibility tree updates.
User settings significantly change behaviour
Punctuation level, verbosity, typing echo, braille mode and other AT settings influence what users hear and when they hear it.
Always verify with real AT and browser combinations
No diagram can capture all timing variations. Real behaviour depends on the interaction between JavaScript, the event loop, the browser engine, the OS accessibility API and the AT client
Footnotes
- [1] ARIA: Accessible Rich Internet Applications [Back]
- [2] DOM: Document Object Model [Back]
- [3] API: Application Programming Interface [Back]
-
[4]
ElementInternals: A browser API that lets custom elements expose proper semantics to the accessibility tree. [Back] - [5] Text nodes: Nodes in the DOM that contain only text, with no element or markup around them. [Back]
- [6] Promise: A JavaScript object representing a value that becomes available later. [Back]
-
[7]
setTimeout: A browser API that runs a function once after a specified delay. [Back] -
[8]
setInterval: A browser API that runs a function repeatedly at a set time interval. [Back] -
[9]
postMessage: A browser API that sends asynchronous messages between windows, frames, or workers. [Back] -
[10]
Promise.then: A method that adds a callback to run when a Promise resolves. [Back] -
[11]
queueMicrotask: A browser API that schedules a small callback to run at the end of the current task, before rendering. [Back] - [12] MutationObserver: A browser API that watches the DOM for changes and reports them asynchronously. [Back]
- [13] Fetch/XHR: APIs that make network requests and deliver responses asynchronously. [Back]
- [14] WebSockets: A browser API that keeps an open, real-time connection to a server for sending and receiving messages. [Back]
-
[15]
requestAnimationFrame: A browser API that runs a callback before the next screen repaint. [Back] -
[16]
DOM mutations: Changes to the DOM — whether triggered by JavaScript, user interaction, or browser behaviour — such as adding, removing, or updating elements or attributes. [Back] -
[17]
: Functions that run when a Promise resolves (.then/.catchhandlers.then) or fails (.catch). [Back] -
[18]
FinalizationRegistry: A JavaScript API that lets you run cleanup code after objects are garbage-collected. [Back] [Back] - [19] AX API on macOS and iOS: Apple’s Accessibility API that allows macOS and iOS assistive technologies, such as VoiceOver, to read and interact with on-screen content. [Back]
- [20] UIA on Windows: Microsoft’s UI Automation framework, which exposes accessibility information to assistive technologies on Windows. [Back]
- [21] ATK and AT-SPI on Linux: Linux accessibility frameworks where ATK defines accessibility objects and AT-SPI provides the communication layer used by assistive technologies like Orca. [Back]