Landing on a field with the keyboard must not open windows, submit forms or move focus. Examples from permit and filing forms.
Keyboard and switch users move through a page by tabbing. Screen reader users do the same, and mouse users give focus to a field simply by clicking it. In all those cases, receiving focus only means "this is where I am". WCAG 2.1 success criterion 3.2.1 says that when any user interface component receives focus, it must not initiate a change of context: no new window, no form submission, no jump of focus to another control, no navigation to a new page.
Activating a control, for example pressing Enter on a button, can legitimately change context. That is covered by other rules. This one is only about the moment of arrival. Content that appears without changing context (a tooltip, an expanded menu or an inline hint) is not a violation unless focus is also moved.
A common pattern is a convenience feature added to speed up forms: a search box that opens a full-screen overlay as soon as it receives focus, a ZIP field that opens a help window, or a month field that pushes focus to the day field the moment it is focused. For a keyboard user tabbing through a court e-filing or permit form, each of these hijacks the journey. The rule applies equally to the cross-field jump on a mobile app. Related: mobile apps and the Title II rule.
<input id="trip-search" onfocus="openFullScreenSearch()"><input id="trip-search" aria-label="Search stops">
<button type="button" id="open-search">Open full-screen search</button>
<script>
document.getElementById("open-search")
.addEventListener("click", openFullScreenSearch);
</script><input id="permit-no" onfocus="window.open('/help/permit-number')"><label for="permit-no">Permit number</label>
<input id="permit-no" aria-describedby="permit-help">
<p id="permit-help">Printed on the top right of your permit card.
<a href="/help/permit-number" target="_blank" rel="noopener">More help (opens in new tab)</a>
</p>month.addEventListener("focus", () => day.focus());<!-- Let the user move between fields themselves -->
<label for="month">Month</label><input id="month" inputmode="numeric">
<label for="day">Day</label><input id="day" inputmode="numeric">
<label for="year">Year</label><input id="year" inputmode="numeric">// SwiftUI
@FocusState private var focused: Field?
...
.onChange(of: focused) { new in
if new == .address { showFullScreenSearch = true }
}// SwiftUI
TextField("Address", text: $address)
Button("Open full-screen search") { showFullScreenSearch = true }// Jetpack Compose
OutlinedTextField(
value = query, onValueChange = { query = it },
modifier = Modifier.onFocusChanged {
if (it.isFocused) navController.navigate("search")
}
)// Jetpack Compose
OutlinedTextField(value = query, onValueChange = { query = it })
TextButton(onClick = { navController.navigate("search") }) {
Text("Open full-screen search")
}onfocus, addEventListener("focus", focusin and, in native code, focus-change callbacks that navigate or move focus.