ComparisonComparisons

:focus vs :focus-visible

focus matches any element that has focus, even after a mouse click. focus-visible only shows an indicator where the browser decides it’s actually needed.

On this page

Side-by-side comparison

#
  • Matches after a mouse click

    :focus
    Yes, in most browsers, even on buttons
    :focus-visible
    Usually not, except for text fields
  • Matches after Tab navigation

  • Who decides whether to show the indicator

    :focus
    Always matches whenever the element has focus
    :focus-visible
    The browser judges whether the indicator is needed
  • A text field after a mouse click

    :focus
    Matches
    :focus-visible
    Also matches, because you’re about to start typing
  • Browser support

    :focus
    Long-standing, widely
    :focus-visible
    Newer, but also widely
  • Recommendation for focus styling

    :focus
    Only when you want to react to focus regardless of input device
    :focus-visible
    Yes, this is the modern standard for visible focus

Example

#
CSS
button:focus-visible {
  outline: 3px solid #f59e0b;
  outline-offset: 3px;
}
Preview

Click the button with the mouse: there’ll be no outline. Now press Tab: it appears, because you’re navigating with the keyboard.

Definition and usage

#

The :focus pseudo-class matches an element that has focus no matter how it got it: a mouse click, a tap on a phone, or moving there with Tab. In most browsers, clicking a button also gives it focus, which is why an outline appearing after a plain click can be surprising.

:focus-visible is smarter. The browser itself judges whether a focus indicator is actually needed at that moment. After navigating with Tab it always matches, while after clicking a button or link with the mouse it usually doesn’t, because the user can see what they clicked. Text fields are the exception: they match both, because after clicking you’re about to start typing in them anyway.

In practice, it’s worth writing your focus style in :focus-visible rather than :focus. That way, people clicking with a mouse don’t see an outline on every click, while people navigating with a keyboard still get a clear indicator. Never remove the outline with :focus { outline: none } without a replacement like this.

Syntax

#
Syntax
selector:focus { property: value; }
selector:focus-visible { property: value; }

More examples

#
:focus shows an outline even after a click
CSS
button:focus {
  outline: 3px solid #f59e0b;
  outline-offset: 3px;
}
Preview

For comparison: plain :focus shows an outline in most browsers even after a mouse click.

A text field matches both pseudo-classes
CSS
input:focus-visible {
  outline: 3px solid #a78bfa;
}
Preview

A text field matches :focus-visible even after a mouse click, because you’re about to type in it.

Good practices

#
  • Never write :focus { outline: none } without a replacement in :focus-visible, because you take away orientation from people navigating with the keyboard.
  • Style the focus indicator in :focus-visible, so it doesn’t appear on every mouse click.
  • Combine hover effects with keyboard focus: .btn:hover, .btn:focus-visible { ... }.

Related entries

#

Spotted a mistake or missing an example? Write to us.