Keyboard Focus Styles With :focus-visible

This old CSS rule solved a visual annoyance by creating an accessibility problem:

button:focus {
  outline: none;
}

The outline sometimes appeared after a mouse click, so it was removed. Keyboard users lost the indicator that showed where their next action would happen.

:focus-visible gives the browser room to show focus when the interaction method needs it.

Begin with one visible site-wide style

:focus-visible {
  outline: 3px solid currentColor;
  outline-offset: 3px;
}

Or target the common interactive elements explicitly:

a:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: 3px solid currentColor;
  outline-offset: 3px;
}

Keyboard navigation gets a clear indicator. Pointer interaction may not leave the same ring after every click.

:focus describes state; :focus-visible adds a heuristic

:focus matches whenever an element has focus:

button:focus {
  outline: 3px solid blue;
}

:focus-visible matches when the browser determines that a visible indicator is useful:

button:focus-visible {
  outline: 3px solid blue;
}

The browser considers the control and interaction method. It owns the heuristic, so do not treat :focus-visible as a perfect synonym for “keyboard only.”

Whatever selector you choose, avoid this reset:

*:focus {
  outline: none;
}

unless every focusable control receives an equally clear replacement. An imperfect browser outline is more useful than an invisible one.

Components may need a local adjustment

Inputs can use a focus treatment that works with their border:

input:focus-visible,
textarea:focus-visible {
  border-color: #005fcc;
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}

:focus-within can highlight a group when a descendant receives focus:

<div class="field">
  <label for="email">Email</label>
  <input id="email" type="email">
</div>
.field:focus-within {
  border-color: blue;
}

That group highlight is useful context, but it should not replace the input’s own indicator unless the result is just as clear.

A focus style can remain visually quiet:

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
}

Test it against every background, including dark mode. currentColor often helps when the text color already has suitable contrast, but it still needs a real visual check.

The quickest test is the Tab key

Put the mouse aside and try to reach navigation, search, form controls, menus, and footer links. Press Tab through the page and watch the focus path.

If you cannot always tell which control is active, the design is not finished. I use :focus-visible to make focus fit the interface, never as a more sophisticated way to hide it.