Maintaining Focus Outlines for Windows High Contrast Mode


If you're overriding browsers' default focus styles with outline: none;, consider using outline: 3px solid transparent; instead. This is a quick and easy way to remove the outline for most viewing modes, while preserving it for Windows High Contrast Mode users.

Introduction #

👋đŸģ Hey there! Long time no see.

While I've been quiet, I've been working on a complete overhaul of the blog, giving it a fresh coat of paint and leveraging a completely different stack. As I was building out this redesign, I decided to try something I, admittedly, should have been doing much earlier: testing the page in Windows High Contrast Mode.

Windows High Contrast Mode, or WHCM, is an operating system-level setting that, when enabled, replaces the color schemes in supporting applications with a reduced palette. That palette could either be one of the presets or a custom scheme. Supporting browsersGo to footnote [1] will override styles for backgrounds, borders, outlines, and more.

Screenshot of this blog post, viewed in Firefox with a white-on-black high-contrast mode. The site's usual purples have been replaced by black, green, and yellow.
This article, viewed on Firefox with Windows 10's High Contrast Black theme

Tabbing through my site in High Contrast Mode, however, revealed a severe lack of focus indicators.

This isn't High Contrast Mode's default behavior. I had overridden the default focus indicators with outline: none;, and replaced them with my own custom focus styles. These new, custom styles largely depended on changing elements' backgrounds, such as hollowing out the navbar links. Background styles are consistently the first thing to go in High Contrast Mode, however, and so we were left with no visual focus indicators.

And so, the problem at hand: restore focus indicators for High Contrast Mode users, while ideally maintaining the focus styles I already had for most viewing modes.

Maybe Media Queries Can Fix It? #

My first thought was to check for media query options for High Contrast Mode. After all, prefers-color-scheme can be used in many browsers to detect system-level dark mode settings. High Contrast Mode didn't seem far off.

I stumbled upon the -ms-high-contrast media feature, with settings for when High Contrast Mode is enabled, when it's set to black-on-white, and when it's set to white-on-black. When my attempts to use it were made in vain, I found that it had been deprecated since 2018 and was super experimental to begin with. Oops.

Since then, the World Wide Web Consortium has published a working draft with the forced-colors and prefers-contrast media features, but these are still subject to change and don't yet enjoy wide browser support, if any. Perhaps one day.

Media queries wouldn't cut it for this problem.

Transparency Is The Best Policy #

I eventually found my solution in Sarah Higley's excellent Quick Tips for High Contrast Mode. Instead of clearing away the focus indicator with outline: none;, I could do

*:focus {
outline: 3px solid transparent;

That transparent keyword there is making the magic happen. When High Contrast Mode isn't applied, transparent ensures that our focus outline is completely invisible. When High Contrast Mode is turned on, transparent is completely, totally disregarded. Our users are greeted with a focus outline that's 3px thick, or whichever other thickness we pick. It's quick, easy, and memorable, and we don't have to finagle with media queries.

Takeaways #

  1. I should have been testing for High Contrast Mode compatibility much earlier.
  2. Many of the resources out there for High Contrast Mode-compatibile styles are out of date, and recommending the now-deprecated -ms-high-contrast media feature.
  3. Media query support for High Contrast Mode is currently in flux, but we should start to see significant headway soon.
  4. Nine times out of ten, outline: 3px solid transparent; fits my use cases better than outline: none;.

Footnotes #

  1. At this point, Edge, Firefox, and Internet Explorer support Windows High Contrast mode reasonably. Chrome support is hidden behind a flag. | ↩ī¸Ž