Support different color themes with a two-color focus indicator

Do you use the keyboard to surf the web? If so, then you'll appreciate having a clearly visible focus indicator. This accessibility feature is especially important for people with motor impairments who rely on a keyboard, instead of a mouse, to navigate a web page.

In general, I recommend using the :focus-visible pseudo-class to define custom focus indicators. Check out my article “Provide highly visible Keyboard Focus with :focus-visible” for more information. But how do you account for different color themes and dark mode?

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

The elegant solution is: Define a two-color focus indicator that has sufficient contrast against any solid background color. The W3C's Technique C40 recommends this solution as a possible way to conform with the WCAG criteria 2.4.7: Focus Visible and 2.4.13: Focus Appearance.

Demo: Two-Color Focus Indicator

Here's my demo of an accessible two-color focus indicator. You can toggle between light and dark mode using the checkbox labelled “Dark Mode”. Focus on the button and the link with the tab key and observe the focus indicator:

How does this work?

The (not so) secret CSS ingredients

To create the two-color focus indicator, you simply combine the CSS properties outline and box-shadow to draw a light and dark line around the focused element.

:is(a[href], button):focus-visible { /* inner indicator */ outline: 3px #fff solid; outline-offset: 0; /* outer indicator */ box-shadow: 0 0 0 5px #000; }

This way, one of the lines always provides sufficient contrast with the current background color. In my demo, I used a simple combination of pure white and black. But you can also use other colors, as the W3C technique explains:

As long as the two indicator colors have a contrast ratio of at least 9:1 with each other, at least one of the two colors is guaranteed to meet 3:1 contrast with any solid background color.

The two-color focus indicator even works in forced colors mode. If you're not familiar with this feature, then read my article “CSS tweaks for better visibility in Forced Colors Mode”.

Posted on