Use transparent borders and outlines to assist with high contrast mode

It’s tempting to use a sharp box shadow for focus styles to both remove the default focus ring and to get around sharp outline corners. With this method, you can create problems for Windows High Contrast users, so this quick tip will help you get the best of both worlds.


Say you’ve got this nice little button.

See the Pen Button with shadow-based focus that’s not accessible in high contrast mode by Andy Bell (@piccalilli) on CodePen.

Because outline doesn’t clip to the shape of your button if you use border-radius, it can be tempting to use a sharp box-shadow for focus styles.

Code language
css
button:focus {
  outline: none;
  box-shadow: 0px 0px 0px 3px #192a56;
}

With standard operating system and browser settings this looks fine. There’s plenty of contrast and the focus style is very clear. Job done, right? Unfortunately not because in Windows High Contrast Mode, both the background and focus styles probably won’t show up.

Because the background isn’t showing up in high contrast mode, the user has no visual indication of hover or focus events.

There is a solution to this: transparent borders and outlines! First, we add a transparent border to our button:

Code language
css
button {
  border: 1px solid transparent;
  /* all the other CSS */
}

This border is completely invisible and you probably won’t even notice it, but the difference in Windows High Contrast Mode is huge.

The much better button with styles as described in windows high contrast mode

This doesn’t fix the focus style though. It’s best to provide genuine contrast with focus styles so when a keyboard user tabs to your element, they can see that it is focused. To improve the initial focus style, we need to tweak it a bit:

Code language
css
button:focus {
  outline: 2px solid transparent;
  outline-offset: 4px;
  box-shadow: 0px 0px 0px 3px #192a56;
}

See the Pen Button with shadow-based focus that’s still accessible in high contrast mode by Andy Bell (@piccalilli) on CodePen.

We first set a 2 pixel outline and then using the ever-handy outline-offset, push it out by another 4 pixels. Now, when a user focuses our button, it looks great both in a standard operating system and browser configuration and it looks great in Windows High Contrast Mode.

The transparent border helps the button show up better to start with, then the outline adds an even better visual indicator that there has been a focus event.

Here’s all the CSS for the button:

Code language
css
button {
  display: inline-block;
  padding: 0.5rem 2rem;
  font: inherit;
  font-weight: bold;
  border-radius: 2rem;
  border: 1px solid transparent;
  background: #3f25c4;
  color: #ffffff;
  min-width: 10rem;
  cursor: pointer;
}

button:hover,
button:focus {
  background: #8c7ae6;
  color: #000000;
}

button:focus {
  outline: 2px solid transparent;
  outline-offset: 4px;
  box-shadow: 0px 0px 0px 3px #192a56;
}

This is a quick win, for everyone: the visual design is left almost untouched and it’s accessible.