Unexpected context change on input
context/on-input
- WCAG success criterion
- 3.2.2 (level A)
- Outcome class
- Automatic. An automated check that can report a confirmed violation.
- Area
- Accessibility, Navigation & Operation
- Default severity
- medium
- axe-core rule
input-no-context-change
Why we flag this
Confusing changes while filling out forms.
Auto-submit on onchange.
What the rule checks
Scope. Rendered selects, radio buttons and listbox/combobox/radio-role elements; their change handlers and, on the running page, the global functions those handlers call.
Expectation. Fails when changing the control's setting changes the context: an onchange handler that navigates, submits, opens a window or moves focus (F36, F37), or calls a page function that does (seen only on the running page, by the page rule in src/wcag/rules/on_input.rs under the same id). A handler whose effect is not visible (it calls a function that only updates content, or none that the page exposes) needs review; updating content is no change of context. 3.2.2 allows the change when the user is advised before using the control (G13), so an advised control is not a violation (forms_gap_advised_change). A select without handler that is named like a navigation control ("Language", "Country") needs review when neither the page nor its own form offers a submit control; inside a form with a submit control nothing changes before the user submits.
Source. WCAG 2.2 SC 3.2.2 On Input; failures F36, F37; technique G13
Detection: shared; needs dom.
Failing example
The check reports a violation here. Corpus case on_input_context_change, element select#jump. The page may contain further findings for other rules.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>On input: content updates vs. context changes (#657)</title>
<meta name="viewport" content="width=device-width, initial-scale=1"><style>
/* #783: page shell, so the case only reports what it is about */
.skip, nav a { display: inline-block; padding: 12px; min-height: 44px; min-width: 44px; box-sizing: border-box; }
button, input, select, textarea { min-height: 44px; min-width: 44px; box-sizing: border-box; }
input[type="checkbox"], input[type="radio"] { width: 44px; height: 44px; }
</style>
<script>
function applySort(value) { document.getElementById('out').textContent = 'Sorted by ' + value; }
function goTo(value) { window.location.href = value; }
</script>
</head>
<body>
<a class="skip" href="#main">Skip to main content</a>
<header><p>Example Shop</p><nav aria-label="Main"><a href="/" aria-current="page">Home</a> <a href="/help">Help</a></nav></header>
<main id="main">
<h1>Grid options</h1>
<!-- Updates the grid next to it via a script listener: no context change -->
<label for="filter-preset">Filter preset</label>
<select id="filter-preset">
<option>All</option>
<option>Active</option>
</select>
<!-- Inline handler that only updates content: at most needs review -->
<label for="sort-preset">Sort preset</label>
<select id="sort-preset" onchange="applySort(this.value)">
<option>Name</option>
<option>Date</option>
</select>
<!-- Name suggests navigation, effect unknown: needs review, no violation -->
<label for="grid-language">Language</label>
<select id="grid-language">
<option>English</option>
<option>Deutsch</option>
</select>
<!-- Handler navigates via a called function: change of context -->
<label for="jump">Jump to page</label>
<select id="jump" onchange="goTo(this.value)">
<option value="#a">Page A</option>
<option value="#b">Page B</option>
</select>
<!-- Handler submits the form: change of context -->
<form action="#submitted">
<label for="per-page">Rows per page</label>
<select id="per-page" name="per_page" onchange="this.form.submit()">
<option>10</option>
<option>50</option>
</select>
</form>
<!-- Not submit buttons: "go" inside "Google"/"category"/"logo" must not
suppress the review for the language select above -->
<button type="button">Sign in with Google</button>
<button type="button">Category</button>
<button type="button">Logo</button>
<p id="out"></p>
</main>
<footer><p>Example Shop, 2026</p></footer>
</body>
</html>Passing example
The check passes here and reports nothing. Corpus case on_input_context_change, element select#filter-preset. The page may contain further findings for other rules.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>On input: content updates vs. context changes (#657)</title>
<meta name="viewport" content="width=device-width, initial-scale=1"><style>
/* #783: page shell, so the case only reports what it is about */
.skip, nav a { display: inline-block; padding: 12px; min-height: 44px; min-width: 44px; box-sizing: border-box; }
button, input, select, textarea { min-height: 44px; min-width: 44px; box-sizing: border-box; }
input[type="checkbox"], input[type="radio"] { width: 44px; height: 44px; }
</style>
<script>
function applySort(value) { document.getElementById('out').textContent = 'Sorted by ' + value; }
function goTo(value) { window.location.href = value; }
</script>
</head>
<body>
<a class="skip" href="#main">Skip to main content</a>
<header><p>Example Shop</p><nav aria-label="Main"><a href="/" aria-current="page">Home</a> <a href="/help">Help</a></nav></header>
<main id="main">
<h1>Grid options</h1>
<!-- Updates the grid next to it via a script listener: no context change -->
<label for="filter-preset">Filter preset</label>
<select id="filter-preset">
<option>All</option>
<option>Active</option>
</select>
<!-- Inline handler that only updates content: at most needs review -->
<label for="sort-preset">Sort preset</label>
<select id="sort-preset" onchange="applySort(this.value)">
<option>Name</option>
<option>Date</option>
</select>
<!-- Name suggests navigation, effect unknown: needs review, no violation -->
<label for="grid-language">Language</label>
<select id="grid-language">
<option>English</option>
<option>Deutsch</option>
</select>
<!-- Handler navigates via a called function: change of context -->
<label for="jump">Jump to page</label>
<select id="jump" onchange="goTo(this.value)">
<option value="#a">Page A</option>
<option value="#b">Page B</option>
</select>
<!-- Handler submits the form: change of context -->
<form action="#submitted">
<label for="per-page">Rows per page</label>
<select id="per-page" name="per_page" onchange="this.form.submit()">
<option>10</option>
<option>50</option>
</select>
</form>
<!-- Not submit buttons: "go" inside "Google"/"category"/"logo" must not
suppress the review for the language select above -->
<button type="button">Sign in with Google</button>
<button type="button">Category</button>
<button type="button">Logo</button>
<p id="out"></p>
</main>
<footer><p>Example Shop, 2026</p></footer>
</body>
</html>This page is generated from the rule catalogue and the rule contracts; see therule overview for how the outcome classes are derived.