Styling Keyboard Focus in Safari with :focus-visible: Version Behavior and a Practical Setup
How Safari's :focus-visible support differs by version and platform, plus a CSS pattern that keeps keyboard focus visible everywhere while hiding the ring for mouse clicks.
23 Jan 2026, 22:30 UTC

The problem: focus rings that appear for mouse users
A common accessibility complaint runs in both directions. Remove outline on focus and keyboard users lose track of where they are on the page. Keep the default outline and mouse users see an outline flash around every button they click. The CSS :focus-visible pseudo-class exists to resolve this: the browser applies it only when it judges that a visible focus indicator is helpful, which in practice means keyboard-driven focus, while plain :focus matches on every focus event including mouse clicks.
Safari was late to ship :focus-visible compared with Chrome and Firefox, and its behavior differs between macOS and iOS in ways that matter for testing. This guide covers a CSS setup that works across Safari 13 and later, how to verify the heuristic actually triggers, and where Safari's behavior can still surprise you.
What Safari supports, by version
Safari added :focus-visible support starting with Safari 14 (macOS Big Sur, and iOS 14). On Safari 13 and earlier the selector is simply unknown, so any rule using it is dropped entirely — the styles do not partially apply. That has a concrete consequence: if you write a single rule that relies on :focus-visible to show your focus ring, Safari 13 users get no custom focus styling at all and fall back to whatever the browser default does.
On iOS, focus behavior depends on input hardware. With only touch input, tapping a field focuses it without a visible focus ring in most cases. When a hardware keyboard is connected, keyboard navigation (Tab between focusable elements) becomes meaningful and the focus heuristic behaves more like the desktop. Plan testing accordingly: an iPhone or iPad without a keyboard attached will not exercise the same code paths.
A selector strategy that degrades safely
The safest pattern is to give every focused element a visible style via :focus, then remove it only when :focus-visible is supported and does not match. Because Safari 13 does not understand :focus-visible, it ignores the suppression rule and keeps the :focus styling — which is the correct fallback.
/* Baseline: visible focus for everyone, including old Safari */
:focus {
outline: 3px solid #1a73e8;
outline-offset: 2px;
}
/* Modern browsers: hide the ring when focus came from a mouse */
:focus:not(:focus-visible) {
outline: none;
}
/* Optional: a distinct style for keyboard focus specifically */
:focus-visible {
outline: 3px solid #1a73e8;
outline-offset: 2px;
border-radius: 2px;
}Two details matter here. First, do not combine :focus and :focus-visible in one selector list such as :focus, :focus-visible { ... }. Per CSS rules, if any selector in a list is invalid for that browser, the entire rule is discarded — so Safari 13 would drop the whole block, including the :focus part it does understand. Keep them in separate rules.
Second, avoid writing a bare :focus { outline: none; } reset anywhere in your stylesheet. That is the pattern this whole approach replaces, and it silently defeats the fallback for older browsers.
Verifying the behavior in Safari
You do not need a build pipeline to check this. Open Safari (Safari Technology Preview is useful for checking upcoming behavior), enable the Develop menu under Settings → Advanced, and open a test page with the CSS above plus a few links, buttons, and a text input.
- Click a button with the mouse. Expected: no outline appears, because
:focus-visibledoes not match mouse-driven focus. - Press Tab to move focus to the same button. Expected: the blue outline appears.
- Click into a text input. Expected: the outline still appears. Browsers generally treat text fields as always matching
:focus-visible, because the user needs to see where typed input will land — this is intentional, not a bug in your CSS. - To confirm what the browser is matching, select the focused element in the Web Inspector Elements tab and check the Styles panel: you can see whether
:focusor:focus-visiblerules are active, and force pseudo-class states via the element's context menu to compare rendering without tabbing.
For the version check, repeat the Tab test on Safari 13 (macOS Catalina, or a simulator/VM). Expected: the outline appears on both click and Tab, because the suppression rule is ignored. That is the acceptable degraded behavior — visible focus everywhere rather than nowhere.
Known limitations and edge cases
- Heuristics are not contractual. The spec deliberately lets browsers decide when
:focus-visiblematches. Safari's decisions can differ from Chrome's in edge cases such as focus moved programmatically withelement.focus()after a mouse interaction. Test the actual flows in your app rather than assuming cross-browser parity. - Shadow DOM and delegated focus. Components using
delegatesFocuscan produce surprising matches; verify custom elements individually. - Conflicting outlines. If your design system already sets
:focusstyles in a component library, layering the rules above can produce double outlines (one from the component, one from your global rule). Audit for existingoutlineorbox-shadowfocus styles before adding global rules. - Do not rely on proprietary overrides. Safari has internal, non-standard focus-region behavior that occasionally surfaces in old blog posts as a fix. Non-standard properties are not a stable foundation; the standard pseudo-class plus the fallback pattern above covers the supported cases.
Checking the result in practice
The acceptance test is simple and manual: with your CSS deployed, Tab through a representative page in Safari 14+ and confirm a visible indicator on every stop, then click the same controls with a mouse and confirm no persistent outline remains. Then repeat on the oldest Safari you support and confirm the indicator still appears on Tab — even if it also appears on click. If you have analytics on browser versions, the share of Safari 13-and-older traffic tells you how much the degraded behavior matters; for most sites it is a small and shrinking fraction, and the fallback keeps those users fully functional.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.