At Level AAA, a change of context is conforming only if the user explicitly requested it or can turn the automatic change off -- predictability and advance warning are not enough
3.2.5 Change on Request
In Plain Language
3.2.5 Change on Request (Level AAA) permits a change of context -- a new window, a navigation, a significant reflow, a focus jump -- only when the user explicitly requested it, or when a mechanism is available to turn the automatic change off[1]. WCAG's definition of "change of context" covers changes of user agent, viewport, focus, and content that, if not announced, would disorient a user who cannot see the full page.
This is the strict form of 3.2.1 On Focus[2] and 3.2.2 On Input[3]. At Level A those criteria only prohibit unexpected changes on focus and input; at AAA, even a predictable, warned-about automatic change fails unless the user requested it or can switch it off.
Why It Matters
- A screen-reader user who is 40 lines into a virtual-cursor read-through loses their place when the DOM is replaced under them. An auto-refresh, an auto-redirect, or a
window.open()on load forces a re-orient from the top of the new document. - A low-vision user running 400% zoom sees only a small viewport slice. A modal that auto-opens on scroll, or a popup that opens on blur, moves focus and content outside that slice with no warning.
- Users with cognitive and learning disabilities rely on the page being where they left it. Unrequested context changes break the mental model that "I am on this page until I act."
- Switch users and users with motor impairments cannot cheaply recover from an unintended navigation -- every interaction has a cost, and a surprise redirect wastes a budget the interface does not know about.
Examples
This page has moved to a new address.
✔ User clicks a button to navigate -- the change is user-initiated
<p>This page has moved to a new address.</p>
<a href="/new-location">Go to the new page</a>
<!-- User decides when to navigate -->
Uses a meta refresh to auto-redirect:
<meta http-equiv="refresh" content="5;url=/new-page">
✘ Page redirects after 5 seconds with no user action and no way to stop it
<!-- FAILS: auto-redirect without user request -->
<meta http-equiv="refresh" content="5;url=/new-page">
<p>You will be redirected in 5 seconds...</p>
<!-- User has no control over this change -->
✔ User can pause auto-advancing slides and navigate manually
<div role="region" aria-label="Featured products">
<button>Previous</button>
<button aria-pressed="false">Pause auto-play</button>
<button>Next</button>
<div role="group" aria-label="Slide 1 of 3">
Featured product
</div>
</div>
<!-- User can stop automatic context changes -->
Page loads with a script that opens a popup:
window.onload = function() { window.open('/promo'); }
✘ New window opens on page load with no user action and no way to prevent it
<!-- FAILS: opens new window without user request -->
<script>
window.onload = function() {
window.open('/promo', '_blank');
};
</script>
<!-- User did not ask for this window -->
How to Fix It
- Delete client-side auto-redirects. Remove
<meta http-equiv="refresh">with a non-zero timeout and anysetTimeout(() => location.assign(...))pattern. If the resource has moved, return a301or302from the server -- server-side redirects are not context changes under 3.2.5[1]. If you must route client-side, render a link the user clicks. - Trigger
window.open()only from a user gesture. Anonload,scroll,mouseleave, or timer-firedwindow.openfails 3.2.5. Call it only inside aclick(or equivalent keyboard-activated) handler, and mark the trigger with text or an icon that announces the new window. - Give auto-advancing regions a real off switch. Carousels, tickers, live feeds, and polling dashboards that reflow content or move focus need a
buttonwhose pressed state stops the automatic change for the rest of the session. Persist that preference so the user does not have to disable it on every page load. (2.2.2 Pause, Stop, Hide is the Level A floor; 3.2.5 requires the off-switch even when the movement is only a content swap.) - Do not submit forms on
change. A<select>that posts the form from itsonchangehandler, or a filter that navigates on every keystroke, changes context without the user requesting it. Require an explicit Submit or Apply button. This is also how 3.2.1 and 3.2.2 are satisfied at Level A; 3.2.5 closes the loophole where a warning label ("selecting a value will reload the page") would otherwise be treated as sufficient. - Expose a preference to disable automatic updates. For real-time dashboards, live sports scores, and notification streams where polling is the product, add a setting that freezes updates on demand. A "Pause live updates" toggle in the region's header, wired to a
aria-pressedbutton, is the minimum viable mechanism.
References
- [1] W3C (2023). Understanding Success Criterion 3.2.5: Change on Request. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/WCAG22/Understanding/change-on-request.html ↩ ↩
- [2] W3C (2023). Understanding Success Criterion 3.2.1: On Focus. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/WCAG22/Understanding/on-focus.html ↩
- [3] W3C (2023). Understanding Success Criterion 3.2.2: On Input. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/WCAG22/Understanding/on-input.html ↩