Encodera

Thanks for reading!

Donate to the site — we work hard for you.

How to change the focus outline

Short answer

Set your own outline in the :focus-visible pseudo-class. Press Tab to see it:

<style>
  button, a { outline: none; }
  button:focus-visible, a:focus-visible { outline: 3px solid orange; outline-offset: 3px; border-radius: 4px; }
</style>
 
<button>Save</button>
<a href="#">Help</a>

:focus-visible fires when focus should be shown — when moving with the keyboard. A mouse click on the button shows no outline, while a text field always shows it.

Why outline and not border

outline takes no space and does not shift neighboring elements, and outline-offset moves the outline away from the edge. A border changes the element size, and everything around twitches slightly on focus.

Highlighting the whole card

If a card contains a field or a link, the :focus-within pseudo-class or :has(:focus-visible) highlights the whole block:

<style>
  .card { padding: 12px; border: 2px solid silver; border-radius: 8px; }
  .card:has(:focus-visible) { border-color: steelblue; }
</style>
 
<div class="card"><a href="#">Read the article</a></div>

Common mistake

:focus { outline: none; } is written with no replacement. A visitor who does not use a mouse no longer sees where they are on the page. Remove the default outline only together with a clear one of your own.

Functions used in this recipe

  • :focus-visible — Matches a focused element when the browser decides the focus should be visible — usually after keyboard navigation.
  • :focus — Matches the element that currently has focus: a field being typed into, a button selected with Tab.
  • outline — An outline around the element that takes no space and does not shift neighbors.
  • :has() — Matches an element that contains something matching the selector in brackets — the "parent selector".

Thanks for reading!

Donate to the site — we work hard for you.