auditmysitev2.0.2

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.

on_input_context_change.htmlHTML
<!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.

on_input_context_change.htmlHTML
<!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.