WCAG 2.4.7 · Level AA · ADA Title II

Visible keyboard focus and the ADA

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.

Where am I on this page?

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.

How public sites lose the focus ring

  • A global reset that removes outlines from links and buttons.
  • Hover styles that have no keyboard equivalent.
  • Custom checkboxes and filter chips that hide the real input.
  • Cards where the inner link's outline is clipped by 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.

Hover styles need a focus twin

If the interface shows a state on hover, give keyboard focus the same cue.

Incorrect
.nav a:hover { background: #ffe9a8; text-decoration: underline; }
.nav a { outline: 0; }
Correct
.nav a:hover,
.nav a:focus-visible {
  background: #ffe9a8;
  text-decoration: underline;
}
.nav a:focus-visible { outline: 3px solid #0b3d91; outline-offset: 2px; }

Custom filter chips and checkboxes

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.

Incorrect
.chip input { display: none; }
.chip span { border: 1px solid #555; padding: 4px 10px; }
Correct
.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.

Incorrect
.card { overflow: hidden; }
.card a:focus-visible { outline: 2px solid #0b3d91; }  /* clipped */
Correct
.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.

Focus in mobile apps

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:

Incorrect
Button("Reserve") { reserve() }
    .focusEffectDisabled()
Correct
Button("Reserve") { reserve() }
    .focused($reserveFocused)
    .overlay(
        RoundedRectangle(cornerRadius: 8)
            .stroke(Color.blue, lineWidth: reserveFocused ? 3 : 0)
    )

Jetpack Compose:

Incorrect
Modifier.clickable(
    interactionSource = source,
    indication = null,
    onClick = { reserve() }
)
Correct
Modifier.clickable(onClick = { reserve() })
// default indication usually shows focus; verify it is clearly visible (see 1.4.11)

A test routine

  1. Put the mouse away and press Tab through every template. At every stop, can you see where focus is without searching?
  2. Check on each background: light, dark, image, and inside banners.
  3. Check custom controls: chips, switches, tabs, cards, dropdowns.
  4. Switch on a forced-colors mode (such as Windows high contrast) and repeat.

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.

Mistakes and a ship-it list

  • Removing outlines in a reset and promising to add them back later.
  • Using only color change as the focus cue on a low-contrast control.
  • Calling blur() on focus.
  • Styling focus only for links, forgetting buttons, inputs and custom widgets.

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.

Sources

Standard version: WCAG 2.1 (W3C Recommendation, 5 June 2018), as named in the Title II web rule. This page is for informational purposes only and is not legal advice. For binding requirements, refer to the official ADA statute and regulations, and ask a lawyer how they apply to you.

Corpowid is recognized by Gartner

Corpowid has been recognized by Gartner, a leading global research and advisory firm, for our innovation and performance in digital accessibility. These badges reflect our commitment to creating inclusive, AI-powered web experiences.

Have questions about Corpowid?

Let’s connect.

We will get back to you as soon as possible.