Selector pseudo-class :focus-visible
The :focus-visible pseudo-class applies while an
element matches the :focus pseudo-class
The :focus pseudo-class always matches the currently-focused element. The :focus-visible pseudo-class also matches the focused element, but only if the user needs to be informed where the focus currently is.
When the :focus pseudo-class is used, it always targets the currently focused element. This means that when a user employs a pointing device, a visible focus ring appears around the focused element, which some consider obtrusive. The :focus-visible pseudo-class respects user agents’ selective focus indication behavior while still allowing focus indicator customization.
.focus-only:focus {
outline: 2px solid black;
}
.focus-visible-only:focus-visible {
outline: 4px dashed darkorange;
}
Providing a :focus fallback
.button:focus-visible {
/* Draw the focus when :focus-visible is supported */
outline: 3px solid deepskyblue;
outline-offset: 3px;
}
@supports not selector(:focus-visible) {
.button.with-fallback:focus {
/* Fallback for browsers without :focus-visible support */
outline: 3px solid deepskyblue;
outline-offset: 3px;
}
}
:focus vs :focus-visible
:focus
Triggers on:
- mouse click
- keyboard navigation
- programmatic focus
Problem: you get focus styles even when clicking with a mouse (often unwanted).
:focus-visible
Triggers only when the browser thinks focus should be visible, typically:
- keyboard navigation (Tab, Shift+Tab)
- accessibility tools
This is exactly what users expect.
&:focus-visible {
background-color: transparent; // Prevents hover/active styles from interfering with focus
outline: 2px solid var(--color-blue);
outline-offset: -1px;
}