Max Design

Published: | Author: Russ Weakley

There are two CSS pseudo-classes commonly used to style elements when they receive focus: :focus and :focus-visible.

This article first explains how they differ, then outlines a series of tests used to understand how they behave across different browsers and form controls.


What :focus does

:focus applies styles whenever an element has focus. It doesn't matter how the element received focus, as long as it is focused.

With the rule below, a focused button gets a visible ring, including after someone clicks it in browsers where clicking gives the button focus.

button:focus {
  outline: 3px solid #005fcc;
  outline-offset: 2px;
}

What :focus-visible does

:focus-visible applies styles when an element has focus and the browser decides a focus indicator should be shown. That decision can depend on things such as how the person is interacting and the type of element that has focus.

For example, tabbing to a button will usually show a focus ring, while clicking the same button usually will not.

button:focus-visible {
  outline: 3px solid #005fcc;
  outline-offset: 2px;
}

Try it yourself

The two groups below use exactly the same focus ring. The only difference is the selector.

  1. Press Tab to move through the buttons and text field in each group.
  2. Then mouse-click the buttons and text field in each group.

Using :focus

Using :focus-visible

When tabbing, the buttons and text fields in both groups should show blue focus rings.

When mouse-clicking:


The tests

The examples above demonstrate the basic difference between :focus and :focus-visible. But the actual browser behaviour is more complex.

These tests aimed to find out, across all form controls tested:

  1. When browsers show a focus indicator.
  2. When :focus-visible matches.
  3. How that differs from :focus.

Test setup

Form controls tested

The three test pages all used exactly the same form controls:

For the rationale behind the controls included here, see What are form controls?

Three test pages

Test page 1: browser defaults
With no author CSS, to see what the browser does on its own.

Test page 2: using :focus-visible
With a :focus-visible rule, to see whether an author's rule applies in the same places as the browser's own indicator.

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

Test page 3: using :focus
With a :focus rule, to see where it differs from the first two.

:focus {
  outline: 3px solid purple;
  outline-offset: 2px;
}

Each control was checked twice on each test page: once by tabbing to it, and once by clicking it.

Browsers and operating systems

macOS 26.7:

Windows 11:

Safari was tested with "Press Tab to highlight each item on a webpage" turned on, since it is off by default and, without it, TAB skips many form controls.


Results for Test page 1: browser defaults

Tabbing:

Every control shows a focus ring, with three exceptions, all in Safari on macOS:

The ring's colour also varies by platform. Chrome on Windows draws a dark ring rather than the blue one used on macOS.

Clicking:

Text fields and date-related controls show a ring. The following controls do not:

<select> varies by browser and is covered separately.

Detailed results


Results for Test page 2: using :focus-visible

Tabbing:

Clicking:

The main finding is that a :focus-visible rule generally matches the behaviour browsers already use for their own focus styles.

There is one exception: <select> in Chrome on Windows. The browser shows no default ring when it is clicked, but the :focus-visible rule does apply. This is the only difference in the click results, out of 120 comparisons.

This shows that a browser's own focus ring and :focus-visible can produce slightly different results. They usually align, but not always.

Detailed results


Results for Test page 3: using :focus

Tabbing:

Every control that can be reached by TAB shows the purple outline in every browser, including Safari's <input type="range">.

Clicking:

In Chrome and Firefox, on both platforms, every control except <input type="file"> shows an outline when clicked. This means those controls did receive focus in the earlier tests, but the browser chose not to show a focus indicator.

In Safari on macOS, buttons, checkboxes, radios, submit, reset and image controls show no outline at all. These controls do not receive focus when clicked, which is consistent with Safari's mouse-focus behaviour on macOS.

<input type="file"> shows no outline when clicked in any browser tested. Opening the file picker affects focus, so the :focus outline is not visible during this interaction.

Detailed results


Key findings

Finding 1:

Tabbing and clicking often produce different focus results, as expected.

Finding 2:

<input type="file"> behaves differently from the other controls tested. Clicking it opens the system file dialog and moves focus away from the page. After the dialog closes, no visible focus indicator appears on the input.

This occurred in Chrome, Firefox and Safari, with browser defaults, :focus-visible and :focus, and whether a file was selected or the dialog was cancelled.

Finding 3:

The controls that don't show a focus ring when clicked vary slightly between browsers, but generally include:

<select> varies between browsers.

The results are almost identical whether you rely on browser defaults or use your own :focus-visible rule, with the one exception covered above.

Finding 4:

If you want focus styles to appear whenever a control receives focus, regardless of whether it was reached by TAB or click, use :focus.

In these tests, :focus showed an indicator in almost every case, with two notable exceptions:

Finding 5:

Browser default focus styles and :focus-visible generally do not show a focus ring when buttons are clicked.

This means mouse users may not see a persistent visual indication that the button has received focus, even in browsers where it remains focused after the click.

Finding 6:

A missing focus ring matters most when a control keeps focus after it is clicked.

This can happen when you rely on the browser's default focus styles or use :focus-visible.

Some controls, such as <input type="checkbox">, <input type="radio">, &lt;input type="range"> and <select>, can then be operated with the keyboard even though no focus ring is shown.

Using :focus avoids this in browsers where clicking gives the control focus, because the focus style remains visible.

This is probably the most compelling reason to use :focus instead of :focus-visible.


When testing

A missing focus ring after a click could be expected behaviour.

However, you need to check whether the control actually received focus rather than assuming that the browser's default focus behaviour or :focus-visible has been used.