Accessibility Testing for SPAs and Dynamic Content
Single-page apps change without reloading, which is exactly where page-by-page scanners stop looking. Test route changes, focus and live updates the way people actually move through the app.
Ranked by measured impact over the last 30 days1,240 sessions sampled
Example output, produced by Accessible on a test site. Not a customer site, and no customer data is shown.
Why are single-page apps hard to test for accessibility?
Because the accessibility of a single-page app is mostly behaviour. When the view changes without a page load, the app itself has to tell assistive technology what happened — by moving focus, updating the title and announcing status messages. A scanner checks the page it loaded; it never sees whether any of that happens after a click.
Why SPAs break traditional scanners
A traditional page load gives assistive technology a clear signal: a new document, a new title, focus at the top. A client-side route change gives none of that for free. Scanning each route by URL loads it fresh, so every route can pass while navigating between them leaves focus stranded and says nothing.
Dynamic updates have the same problem. WCAG 4.1.3 exists so that status messages “can be presented to the user by assistive technologies without receiving focus” (W3C Web Accessibility Initiative, 2026). Whether a message is announced depends on how and when it was inserted — something only visible while the app is being used.
- Passed. 1 · Sign-in form — labels announced
- Passed. 2 · Submit — error summary takes focus
- Passed. 3 · Dashboard — heading level 1 announced
- Serious. 4 · Search field — placeholder, no label
- Critical. 5 · Results — list replaced silently
- Not evaluated. 6–7 · not reached
Completed 3 of 7 stepsWCAG 4.1.3 · 3.3.2
Example output, produced by Accessible on a test site. Not a customer site, and no customer data is shown.
What breaks in single-page apps
None of these show up in a scan of a freshly loaded route. All of them show up the first time someone uses the app with a keyboard or screen reader.
Route changes nobody is told about
A link swaps the view without a page load. The browser does not announce a new page, the title may not change, and a screen-reader user hears nothing — or the rest of the old page.
WCAG 2.4.2 · 4.1.3
Focus left behind, or dropped
After navigation, focus stays on a link that no longer exists or falls back to the page body, so the next Tab starts from the top of the document instead of the new content.
WCAG 2.4.3
Content replaced silently
Search results, filters, infinite scroll and "load more" update the list with no status message, so there is no way to know anything happened without re-reading the page.
WCAG 4.1.3
Live regions that never speak
A live region rendered at the same moment as its text, or re-created on every update, is often not announced at all. The region has to exist before the message arrives.
WCAG 4.1.3
Dialogs, drawers and menus
Components mounted on demand open without moving focus into them, let focus escape behind them, or close without returning focus to the control that opened them.
WCAG 2.1.2 · 2.4.3
Loading states with no words
A spinner or skeleton says "wait" visually. Without a status message, a screen-reader user cannot tell loading from broken.
WCAG 4.1.3
Testing focus management and live regions
Focus after every change
For each route change, dialog and in-place update, check three things: where focus lands, whether that place makes sense for what just happened, and where focus returns when a temporary view closes. After navigation, focus belongs at the start of the new content; after a dialog closes, it belongs on the control that opened it. The focus management guide walks through each case.
Announcements for every update
Trigger each update with a screen reader running and listen. Results counts, errors, confirmations and loading states should be announced without stealing focus. When they are not, check that the live region exists before the message is inserted and is not re-rendered with it. The ARIA live region testing guide covers the patterns that fail silently.
How Accessible covers single-page apps
Route changes and in-place updates need something that uses the app, not something that loads it.
Journeys use the app
A simulated screen-reader user attempts a task keyboard-only, and after every click or keystroke checks what was announced, where focus landed and whether a status message was spoken — then reports the step where the task stopped.
How journey testing worksMonitoring watches real navigation
Real user monitoring checks where focus landed after every client-side route change in visitors’ sessions, detects focus traps and focus that is not visible, and ranks each barrier by how many sessions met it.
How monitoring worksScanning covers every route
Automated scanning checks each route’s markup in a real browser for the failures a machine can decide, and routes found by monitoring are surfaced so they can be added to the scan list.
How scanning works
Sources
- Understanding Success Criterion 4.1.3: Status Messages (opens in a new tab). W3C Web Accessibility Initiative, May 11, 2026.
Frequently asked questions
Why do automated scanners miss accessibility issues in single-page apps?
A scanner loads a URL and checks the page it gets. In a single-page app most of what matters happens after that: route changes without reloads, content swapped in place, dialogs mounted on demand. Focus management and announcements during those changes never exist in a freshly loaded page, so a scan cannot see them.
How should focus be handled after a route change in an SPA?
Move focus to the start of the new content — typically its main heading or container, made focusable with tabindex="-1" — and update the document title, so keyboard and screen-reader users land in the new view and know where they are. Leaving focus on the old link or on the page body is a WCAG 2.4.3 failure.
How do I test ARIA live regions in a single-page app?
Trigger each update — a search, a filter, an add-to-cart — with a screen reader running and listen for the announcement. Check that the live region is present in the page before the update, that it is not re-created each time, and that the message makes sense on its own.
Does Accessible catch focus lost after client-side navigation?
Yes, two ways. Journeys check where focus landed after every click and keystroke while attempting a task. Real user monitoring checks where focus landed after every client-side route change in real visitors’ sessions, and reports the routes where it was lost.
See what happens after the first click.
Run a journey through your app, and monitor focus in real visitors’ sessions after every route change.