CSS Focus Styles

CSS focus styles provide a visible indication of which interactive element currently has keyboard focus. Clear focus indicators help people navigate links, buttons, form controls, and other interactive content without relying on a mouse or touchscreen.

Browsers provide default focus indicators, but CSS can customize them when a design requires a different appearance. Custom focus styles should remain easy to see and should not remove useful browser behavior without providing an accessible replacement.

Understanding Keyboard Focus

Keyboard focus identifies the interactive element that is currently ready to receive keyboard input. People commonly move through focusable elements with the Tab key and move backward with Shift+Tab.

Links, buttons, form controls, and certain other interactive elements can normally receive focus. A visible focus indicator lets the user see where keyboard interaction will occur.

For example, when a button receives focus, pressing Enter or Space can activate it according to the button's normal keyboard behavior.

The :focus Pseudo-class

The :focus pseudo-class selects an element while it has focus.

a:focus {
  outline: 3px solid #0088cc;
}

This rule displays a solid outline around a link whenever that link matches :focus.

The pseudo-class can be used with buttons, form controls, links, and other focusable elements.

button:focus {
  outline: 3px solid #0088cc;
}

The :focus pseudo-class is based on whether the element has focus, regardless of how focus was obtained.

The :focus-visible Pseudo-class

The :focus-visible pseudo-class allows the browser to determine when a visible focus indicator should be shown based on the interaction method and browser heuristics.

button:focus-visible {
  outline: 3px solid #0088cc;
  outline-offset: 3px;
}

This is particularly useful when a strong focus indicator is desired for keyboard navigation without necessarily displaying the same custom indicator after every pointer interaction.

Browsers can still determine that a focus indicator is appropriate in situations other than keyboard navigation, such as when an element requires keyboard input.

The :focus-within Pseudo-class

The :focus-within pseudo-class selects an element when that element or one of its descendants has focus.

.form-group:focus-within {
  background-color: #f2f8fb;
}

This can visually identify a larger group while a control inside that group is focused.

.form-group:focus-within {
  border-color: #0088cc;
}

For example, a form field's container can change its border or background while its input has focus, helping connect the focused control with related content.

Using outline for Focus

The outline property is well suited to focus indicators because it draws a line around an element without taking up space in normal layout.

a:focus-visible {
  outline: 3px solid #0088cc;
}

Unlike a border, an outline does not change the element's dimensions or move nearby content when it appears.

The outline can be customized with width, style, and color values.

button:focus-visible {
  outline-width: 3px;
  outline-style: solid;
  outline-color: #0088cc;
}

Using outline-offset

The outline-offset property adds space between an outline and the edge of an element.

button:focus-visible {
  outline: 3px solid #0088cc;
  outline-offset: 3px;
}

A positive offset moves the outline away from the element, which can make the focus indicator easier to distinguish from the element's border or background.

Negative values move the outline inward.

button:focus-visible {
  outline-offset: -3px;
}

When using an inward outline, make sure it remains clearly visible against the element's own colors.

Focus Indicator Contrast

A focus indicator needs enough visual contrast to remain distinguishable from surrounding colors. A focus color that works against one background may be difficult to see against another.

Focus styles should therefore be tested wherever the focused element can appear, including light, dark, colored, and image backgrounds.

One approach is to combine more than one visual treatment.

button:focus-visible {
  outline: 3px solid #000;
  outline-offset: 3px;
  box-shadow: 0 0 0 6px #fff;
}

Using contrasting layers can help keep the indicator visible against a wider range of surrounding colors. The specific colors should be chosen for the page where the control appears.

Do Not Remove Focus Indicators

A common accessibility problem occurs when CSS removes the browser's focus indicator without providing a visible replacement.

button:focus {
  outline: none;
}

Used by itself, this rule can make it difficult or impossible for keyboard users to determine which button currently has focus.

If the browser's default focus appearance is removed, provide another clearly visible focus indicator.

button:focus-visible {
  outline: 3px solid #0088cc;
  outline-offset: 3px;
}

In many cases, leaving the browser's default focus indicator unchanged is preferable to removing it without a carefully tested replacement.

Focus Style Practices

Practice Purpose
Keep focus visible Allows users to identify the currently focused element.
Use clear contrast Helps distinguish the indicator from nearby colors.
Use sufficient thickness Makes the indicator easier to perceive.
Test keyboard navigation Confirms that focus can be followed through interactive content.
Use :focus-visible appropriately Allows custom focus styling to respond to browser focus-indicator heuristics.
Avoid layout shifts Prevents focus styling from moving surrounding content.

Focus styling is only one part of keyboard accessibility. Interactive elements must also appear in a logical focus order and provide appropriate keyboard behavior.

CSS Focus Styles Example

The following example gives links, buttons, and form controls a clearly visible focus indicator using :focus-visible.

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

Open the example in the editor and use the Tab key to move between the interactive elements. Try changing the outline width, style, color, and offset to see how each value affects the focus indicator.

Play in Editor