albert.walickihire me
← all solutions
css

How to remove the focus outline from inputs and buttons?

Removing the focus outline breaks keyboard navigation. Use :focus-visible to hide it on mouse clicks and replace it with your own accessible focus style.

outline: none removes it, but don't ship that on its own. The outline is how keyboard users see where they are on the page, and removing it fails WCAG 2.4.7 Focus Visible. The real fix is to replace the default ring with your own style, shown only when it's needed, using :focus-visible:

:focus-visible {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}

Browsers match :focus-visible when focus should be visible: after Tab or other keyboard navigation, but not when you click a button with the mouse. The ring you didn't want after a click goes away, and keyboard users keep theirs.

Make the custom style easy to see. A 2px outline in a color with at least 3:1 contrast against the background is a good baseline. Outlines follow border-radius in current browsers, so rounded buttons don't need a box-shadow trick for this.

Why you see a ring after clicking

Current browsers already draw their default focus ring with :focus-visible, so a plain button shouldn't show one after a mouse click. If yours does, some CSS is styling :focus instead, usually a reset, a UI library or an old snippet. Move those styles to :focus-visible:

/* Before: shows on every click */
.button:focus {
  outline: 2px solid #2563eb;
}

/* After: shows for keyboard focus */
.button:focus-visible {
  outline: 2px solid #2563eb;
}

Also look for global rules like *:focus { outline: none; } and delete them.

Text inputs show focus on click, and that's intended

Text inputs and textareas match :focus-visible even when you click them, because the user is about to type and needs to see which field is active. Don't remove it. Restyle it so it fits your design:

.input {
  border: 1px solid #d1d5db;
  border-radius: 6px;
}

.input:focus-visible {
  border-color: #2563eb;
  outline: 2px solid transparent;
  box-shadow: 0 0 0 3px rgb(37 99 235 / 40%);
}

Keep an outline for forced colors mode

The transparent outline above isn't a mistake. When Windows High Contrast is on, the browser switches to forced colors mode: it drops box-shadow and replaces your colors with system colors. A focus style made of outline: none and a box-shadow disappears completely there. A transparent outline gets a visible system color instead, so the focus indicator survives.

You can check it without Windows: Chrome DevTools can emulate forced-colors: active in the Rendering panel.

The mobile tap highlight is something else

The gray or blue flash when you tap a link or button on a phone isn't the focus outline, and outline: none doesn't touch it. It has its own non-standard property:

.button {
  -webkit-tap-highlight-color: transparent;
}

Removing the tap highlight is fine as long as the button has its own :active style, so people still get feedback when they tap.

more solutions
work with me

Got something that needs building?

Frontend builds, full-stack features in Django, design-system work. Available for work.

See my workGet in touch