Provide highly visible Keyboard Focus with :focus-visible

Fancy design or accessibility? The :focus-visible pseudo-class enables you to support keyboard-only users and, at the same time, satisfy the aesthetic expectations of your clients.

Closeup of a person's hands typing on a laptop keyboard Photo: © cottonbro / pexels.com

The Importance of Keyboard Focus

Being able to navigate with a keyboard is an important feature of accessible websites. This benefits people with motor impairments who rely on a keyboard, instead of a mouse, to navigate a web page. Providing a visual indicator that clearly highlights the element that currently has keyboard focus is therefore indispensable.

Browsers provide a default focus indicator to ensure that keyboard focus is visible. In CSS, the styling of the focus indicator can be changed via the :focus pseudo-class. For example:

button:focus { outline: 2px solid purple; }

Design versus Accessibility

I think we can all agree that a visual focus indicator is very helpful for keyboard users. On the other hand, the focus indicator also appears when users click an element with a mouse or touch it with their finger. For some users, this can be distracting or even irritating. Especially, without the knowledge that highlighting the element is actually an accessibility feature.

Often, web developers have to deal with clients and designers, who insist that they remove the focus styles altogether for purely aesthetic reasons. Consequently, many websites define CSS rules like this one:

button:focus { outline: none; }

Please, don't do this! You would actively exclude people who depend on keyboard navigation.

The Solution is :focus-visible

There is a way to reconcile accessibility with design expectations: The :focus-visible pseudo-class. The specification states:

The :focus-visible pseudo-class applies while an element matches the :focus pseudo-class and the user agent determines via heuristics that the focus should be made evident on the element.

This means: It lets you show focus styles only when they are needed, that is to say, when an element receives focus and the browser determines that the focus indicator should be shown (e.g., on keyboard navigation).

/* Hide focus styles if they're not needed. */ button:focus:not(:focus-visible) { outline: none; } /* Show focus styles on keyboard focus. */ button:focus-visible { outline: 2px solid purple; }

This way, you gain precise control over when the focus indicator of e.g., buttons and links is shown. For some elements like input fields, the focus indicator will still be shown when the users click on it. This is because clicking the input field activates keyboard input. You can test this behavior in my demo.

Browser Support

Most modern browsers already support the feature. Safari also added support for :focus-visible with version 15.4. Still, I'd recommend you define regular focus styles for non-supporting browsers and then overwrite them for browsers that support :focus-visible.

/* Regular focus styles for non-supporting browsers. */ button:focus { outline: 2px solid purple; } /* For browsers that support :focus-visible */ @supports (:focus-visible) { button:focus:not(:focus-visible) { outline: none; } button:focus-visible { outline: 2px solid purple; } }

Useful Links

Update on 04/14/2022

Post updated for Safari 15.4.

Posted on