Keyboard users need to see where they are. Hiding the focus outline, or styling it so it disappears on some backgrounds, makes a page unusable for them.
Keyboard focus is the keyboard user's cursor. If it cannot be seen, pressing Enter is a gamble. People who use a keyboard because of a motor disability, people who use switch devices, and people with low vision who rely on a clear indicator are all affected, and so is anyone with attention or memory difficulties.
Success Criterion 2.4.7 says any keyboard operable interface has a mode of operation where the keyboard focus indicator is visible. The browser's default outline meets it as long as it is clearly visible on your backgrounds. The failure usually comes from removing it, or from replacing it with something that cannot be seen. The indicator does not need to be visible at all times for mouse users, but once keyboard focus is shown, it must stay visible while the element is focused.
How strongly the indicator contrasts with its surroundings falls under 1.4.11, Non-text Contrast, and is not repeated here.
overflow: hidden.A site can look polished with a mouse and give a keyboard user nothing at all. Library catalogs and park reservation pages with custom filters are common examples.
If the interface shows a state on hover, give keyboard focus the same cue.
.nav a:hover { background: #ffe9a8; text-decoration: underline; }
.nav a { outline: 0; }.nav a:hover,
.nav a:focus-visible {
background: #ffe9a8;
text-decoration: underline;
}
.nav a:focus-visible { outline: 3px solid #0b3d91; outline-offset: 2px; }Hiding the native input with display: none also removes it from keyboard navigation. Hide it visually, keep it focusable, and show the focus on its label.
.chip input { display: none; }
.chip span { border: 1px solid #555; padding: 4px 10px; }.chip { position: relative; }
.chip input {
position: absolute; opacity: 0;
width: 1px; height: 1px;
}
.chip span { border: 1px solid #555; padding: 4px 10px; }
.chip input:focus-visible + span {
outline: 3px solid #0b3d91; outline-offset: 2px;
}If the card clips the outline, show focus on the whole card instead.
.card { overflow: hidden; }
.card a:focus-visible { outline: 2px solid #0b3d91; } /* clipped */.card { overflow: hidden; }
.card:has(a:focus-visible) {
outline: 3px solid #0b3d91;
outline-offset: 2px;
}:has() is supported in current browsers. If you must support older ones, apply the focus ring inside the card with box-shadow: inset.
Hardware keyboards and switch control show focus in native apps too. Do not turn the system indicator off without a replacement (focusEffectDisabled() needs iOS 17). SwiftUI:
Button("Reserve") { reserve() }
.focusEffectDisabled()Button("Reserve") { reserve() }
.focused($reserveFocused)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(Color.blue, lineWidth: reserveFocused ? 3 : 0)
)Jetpack Compose:
Modifier.clickable(
interactionSource = source,
indication = null,
onClick = { reserve() }
)Modifier.clickable(onClick = { reserve() })
// default indication usually shows focus; verify it is clearly visible (see 1.4.11)Search the stylesheets for outline: none and outline: 0 and confirm each has a visible replacement. Automated tools often catch this, but they cannot see whether a replacement is visible on a real background.
blur() on focus.Ship it when every interactive element shows a visible focus indicator on every background it can appear on, and the indicator stays while the element is focused.
The DOJ lists mouse-only navigation among common barriers; see common barriers.