WCAG 2.4.7 · Level AA · EN 301 549 9.2.4.7

Focus Visible

Requires that the keyboard focus indicator is visible whenever a keyboard-operable interface is used.

In brief

When you use a keyboard, the focus indicator is your cursor. If you cannot see where focus is, you do not know what a key press will do. Removing the outline with outline: none is one of the most common accessibility mistakes on the web.

This criterion requires that any keyboard-operable user interface has a mode of operation where the keyboard focus indicator is visible. The criterion does not prescribe how the indicator looks. The browser default is acceptable, and so is a custom style.

What does it cover?

  • Visible focus: When an element receives keyboard focus, something visible must change: an outline, a border, a background or similar.
  • Default is fine: The user agent's default indicator satisfies the criterion (G149, G165). The failure comes when it is removed or hidden.
  • Custom indicators: You can design your own with CSS (C15, C45), a two-colour indicator that works on any background (C40), or script (SCR31).
  • A mode of operation: The indicator may appear only during keyboard use, as with :focus-visible, as long as there is a mode in which it is visible.
  • It must stay: The indicator must not disappear after a delay while the element still has focus.
  • Failures: Removing focus with script (F55) and removing outlines or borders without a replacement (F78).
  • Out of scope: The contrast of the indicator against its surroundings is 1.4.11. Not hiding the focused element behind other content is 2.4.11. Size and thickness requirements for the indicator are 2.4.13 (Level AAA).

Who does it affect?

Keyboard users, switch users and people who use voice control or other devices that behave like a keyboard. People with attention, short-term memory or executive function difficulties, who need to see where they are. People with low vision, who need a clear indicator. Mouse users also benefit.

In the EAA and EN 301 549

The European Accessibility Act (Directive (EU) 2019/882) applies to in-scope products and services placed on the market after 28 June 2025. Recital 47 names four principles for websites and mobile applications: perceivable, operable, understandable and robust. A visible indication of where you are is part of "operable".

The technical counterpart is the standard EN 301 549, which incorporates WCAG 2.4.7 by reference and turns it into separate clauses for each kind of ICT.

Where WCAG 2.4.7 appears in EN 301 549
ClauseType of ICTWhat it requires
9.2.4.7Web pagesWeb content must satisfy WCAG success criterion 2.4.7.
10.2.4.7Non-web documents (PDF, Office files)Documents must show a visible keyboard focus indicator where the standard applies the criterion to them.
11.2.4.7Non-web software (native mobile apps)Software must provide a visible keyboard focus indicator.

Whether and how the criterion applies to non-web documents is stated in clause 10 of the standard. Clause numbers follow the "9. + WCAG number" pattern of EN 301 549. In V3.2.1 the software clause is divided into further subclauses for open and closed functionality. Check the exact numbers in the standard when you cite them.

Standard version: EN 301 549 V4.1.1 (September 2026) is based on WCAG 2.2 and is the first version prepared specifically for the EAA. It has not yet been cited in the Official Journal of the European Union, so for now it is best treated as a voluntary technical route to the EAA's requirements. Once cited, it will give a presumption of conformity. The text of criterion 2.4.7 is the same in WCAG 2.1 and 2.2. It is a Level AA criterion.

A note on EAA scope: Article 2(4) of the Directive excludes certain content from the requirements, for example office file formats published before 28 June 2025 and archives that are not updated after that date. Content you publish or change after that date is not covered by these exclusions.

Directive (EU) 2019/882, EUR-Lex, opens in a new tab

Code examples for the web

1. Do not remove the outline

This single line breaks keyboard use on a whole site.

Incorrect
*:focus { outline: none; }
Correct
/* Keep the default, or replace it with something clearly visible */
:focus-visible {
  outline: 3px solid #0b5fff;
  outline-offset: 2px;
}

2. A custom focus style for keyboard users

:focus-visible shows the indicator for keyboard use and not for mouse clicks.

Incorrect
button:focus { outline: 0; }
Correct
button:focus-visible {
  outline: 3px solid #0b5fff;
  outline-offset: 2px;
}

3. A two-colour indicator that works on any background

A single colour can disappear against some backgrounds. Two colours always contrast with one of them (C40).

Incorrect
a:focus-visible { outline: 2px solid #ffffff; } /* invisible on a white page */
Correct
a:focus-visible {
  outline: 2px solid #ffffff;
  box-shadow: 0 0 0 4px #000000;
}

4. Custom components

Custom controls need their own focus style. Do not rely on the default if you have hidden the native control.

Incorrect
.switch input { position: absolute; opacity: 0; } /* nothing shows focus */
Correct
.switch input { position: absolute; opacity: 0; }
.switch input:focus-visible + .track {
  outline: 3px solid #0b5fff;
  outline-offset: 2px;
}

5. Do not remove focus with script

Calling blur() on focus defeats keyboard use (F55).

Incorrect
el.addEventListener("focus", () => el.blur());
Correct
// Let focus stay on the element and style it

6. Respect forced colours

In Windows High Contrast mode, author colours are overridden. A transparent outline remains visible there.

Incorrect
.btn:focus-visible { box-shadow: 0 0 0 3px #0b5fff; } /* disappears in forced colours */
Correct
.btn:focus-visible {
  box-shadow: 0 0 0 3px #0b5fff;
  outline: 3px solid transparent; /* visible in forced colours */
}

Code examples for mobile

Native apps are used with hardware keyboards, switch control and full keyboard access. System controls show focus by default. Custom controls need their own focus indicator.

iOS (SwiftUI)

import SwiftUI

struct TagChip: View {
    let title: String
    @FocusState private var focused: Bool

    var body: some View {
        Text(title)
            .padding(8)
            .focusable()
            .focused($focused)
            // A custom chip needs its own visible focus indicator
            .overlay(
                RoundedRectangle(cornerRadius: 8)
                    .stroke(focused ? Color.blue : Color.clear, lineWidth: 3)
            )
    }
}

Android (Jetpack Compose)

import androidx.compose.foundation.border
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

@Composable
fun TagChip(title: String) {
    var focused by remember { mutableStateOf(false) }
    Text(
        text = title,
        modifier = Modifier
            .onFocusChanged { focused = it.isFocused }
            .focusable()
            // A custom chip needs its own visible focus indicator
            .border(if (focused) 3.dp else 0.dp, Color(0xFF0B5FFF), RoundedCornerShape(8.dp))
            .padding(8.dp)
    )
}

How to test

  • Tab through the page: Can you always see where focus is? Check links, buttons, form fields, menus, custom widgets and cards.
  • Check the CSS: Search for outline: none, outline: 0 and :focus { ... } resets, and check that each is replaced by a visible style.
  • Check custom components: Toggles, checkboxes and custom selects often hide the native input. Does focus still show?
  • Check on each background: A focus indicator can vanish on dark or on image backgrounds. Test there.
  • Check forced colours: Turn on Windows High Contrast or forced colours mode in the browser developer tools.
  • Check that it stays: Does the indicator remain visible while the element has focus, without disappearing after a delay?
  • Check mobile: Connect a keyboard or switch control. Is focus visible on every control, including custom ones?
  • Use a checker as a starting point: Automated tools can find CSS that removes outlines, but cannot see whether a replacement is visible.

Common mistakes

  • outline: none with no replacement: The most common accessibility mistake on the web.
  • Resetting styles with * { outline: 0 }: A global reset removes focus everywhere.
  • A custom indicator that is too faint: A 1px light grey line is not visible.
  • A hidden native input in a custom control: Focus goes to an invisible element.
  • Removing focus with script: blur() on focus.
  • An indicator only on hover: Keyboard users never hover.
  • A single-colour indicator: It disappears on the wrong background.
  • Ignoring forced colours: The indicator vanishes in high contrast mode.

Sources

Standard version: EN 301 549 V4.1.1 (2026-09), WCAG 2.2. This page is for informational purposes only and is not legal advice. For binding requirements, refer to the official texts of the European Accessibility Act (Directive (EU) 2019/882) and EN 301 549.

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.