WHCM and System Colors
There is a ton of prior content discussing Windows High Contrast Mode (WHCM) and web content. The catch is that content covers four (five?) different implementations across more than a decade of support: Internet Explorer, Edge, the other Edge, Edge plus IE aliasing, and hardly anything on Firefox. Which means much of it no longer applies.
The best overview of the current situation is from Microsoft: Styling for Windows high contrast with new standards for forced colors, posted mid-September 2020. As the standards process moves forward and Edge continues to update, expect this overview to be updated (or point to updates).
That post covers the basics of the feature (I do not). Because I want you to try my examples, this is how to activate WHCM:
- Start → Settings → Ease of Access → High contrast, then “Turn on high contrast”, then “Choose a theme” (if you want to try variations)
- Alt + left Shift + Print Screen (activates the last-used theme)
Please remember that High Contrast Mode is used by some to produce low contrast screens.
The typical contrast of the operating system or the web can be uncomfortable for many people. The most common use case might be someone prone to migraines. High Contrast Mode allows them to create a low contrast palette to help mitigate that.
Remember as you go down this path that your role as the developer is not to increase the contrast of everything on the screen, but to honor the user settings and system color preferences.
As you read this, I want your primary takeaway to be that you likely will need to do little for standard document pages. If you have some novel custom widgets, then please add and use styles with keywords that correspond to function. If you need to retain some coloring for important contextual reasons, then look at the overrides.
Feature Queries
Since Microsoft introduced WHCM, Internet Explorer had good reason to support a feature query to detect it and allow developers to tweak and override how the styles are applied.
First I want to qualify that if you are using standard HTML, you should not need these. Plain text and native controls adapt just fine. The problems come when you start to introduce custom widgets, ARIA properties, necessary visual flourishes, and so on.
You should only ever use these feature queries to spackle over gaps (found in most libraries / frameworks) or enhance an experience that may be lacking.
Proprietary, or Internet Explorer Only
In Internet Explorer you can use a proprietary feature query to detect if WHCM is active, along with another to detect if the WHCM setting is light on dark, or dark on light. I advise you to only check if it is active (the first from the following set).
@media screen and (-ms-high-contrast: active) {
/* put your custom styles here */
}
@media screen and (-ms-high-contrast: black-on-white) {
/* put your custom styles here */
}
@media screen and (-ms-high-contrast: white-on-black) {
/* put your custom styles here */
}
I identify the six system colors available to you below in the WHCM Proprietary Feature Query Color Mappings section. However, you shouldn’t be too worried about those unless you are fixing broken custom controls. I encourage you to read Greg Whitworth’s overview of how to use -ms-high-contrast
well.
Instead you can use this feature query to tweak things like spacing or even disable some unwanted features via -ms-high-contrast-adjust
:
@media screen and (-ms-high-contrast: active) {
selector {
-ms-high-contrast-adjust: none;
}
}
If you are still somehow supporting Legacy Edge (Ledgacy), these feature queries and custom properties apply there as well.
Standards Track, or Edge Only
To disambiguate, when I reference Edge here I am talking about ChromiEdge, or the version of Edge built on Chromium. As of this writing, Legacy Edge is nearly gone in the wild and will be wiped from hold-out computers in non-locked-down environments in April 2021.
Sometime in the future I hope to remove the “or Edge Only” from that heading. I hope that the work Edge has done in Chromium gets slurped up to the Chrome engine, copied into Firefox, and somehow maybe even replicated in Safari with a similar macOS-level contrast setting.
Until then, the proposed forced colors mode feature of the CSS Color Adjustment Module Level 1 Working Draft has just the one browser supporting it.
In this case the syntax is easier since either the forced colors mode is on or not.
@media screen and (forced-colors: active) {
/* put your custom styles here */
}
The following properties are affected:
color
fill
stroke
text-decoration-color
text-emphasis-color
border-color
outline-color
column-rule-color
scrollbar-color
-webkit-tap-highlight-color
background-color
I was glad to see scrollbar in there given the resurgence of folks making terribly styled scrollbars
As with the proprietary feature, you also have the option to opt out of the color overrides. This is handy in cases where the colors are important to convey something without changing, such as paint, lipstick, or underpants. In those scenarios you would use forced-color-adjust
:
@media screen and (forced-colors: active) {
selector {
forced-color-adjust: none;
}
}
Frankenquery’s Monster
Frankenquery is the name of the scientist. Its monster is this:
@media screen and (-ms-high-contrast: active),
screen and (forced-colors: active) {
selector {
-ms-high-contrast-adjust: none;
forced-color-adjust: none;
}
}
You could use this to target all the supporting browsers in one block. But be certain your system color keywords work across them all or that you override in the correct order. You may also want more targeted styles if you are trying to replicate native WHCM colors with your custom controls, considering native elements are a bit different between IE11 and Edge.
System Colors
Pulling from system colors means you will generally be leaning on what the user prefers, or at least what they are used to. CSS 2 introduced system font keywords in 1998 (which I wrote about in 2015 when Apple did its own thing), so the notion of using the operating system as a source is not new.
CSS2 System Color Keywords
CSS2 defined 28 keywords which were later carried into CSS Color Module Level 3 System Color Keywords (and then deprecated). From the names, you can guess on the effort to replicate the 3D effects of Microsoft Windows.
In the context of my anecdote, when Windows High Contrast Mode was introduced, using the system color keywords meant no extra work was needed because we had already mapped all the system colors to their native HTML equivalents. Even with the reduced set supported in WHCM, no extra work was needed on our part.
ActiveBorder
ActiveCaption
AppWorkspace
Background
ButtonFace
ButtonHighlight
ButtonShadow
ButtonText
CaptionText
GrayText
Highlight
HighlightText
InactiveBorder
InactiveCaption
InactiveCaptionText
InfoBackground
InfoText
Menu
MenuText
Scrollbar
ThreeDDarkShadow
ThreeDFace
ThreeDHighlight
ThreeDLightShadow
ThreeDShadow
Window
WindowFrame
WindowText
WHCM Proprietary Feature Query Color Mappings
Internet Explorer recognizes a reduced set of these keywords in WHCM. Hyperlinks use the proprietary -ms-hotlight
. Handy if using the proprietary feature query in Internet Explorer
ButtonFace
ButtonText
Highlight
HighlightText
Window
WindowText
GrayText
-ms-hotlight
CSS4 System Color Keywords
CSS Color Module Level 4 introduced a different set of system color keywords, dropping the count to 19 (updated 13 July 2022, it was 15 when I first wrote this post) and eliminating all the 3D detail.
This reduced set of keywords comes with a warning to ensure you pair background and foreground sets for better contrast.
Canvas
CanvasText
LinkText
VisitedText
ActiveText
ButtonFace
ButtonText
ButtonBorder
Field
FieldText
Highlight
HighlightText
Mark
MarkText
GrayText
SelectedItem
SelectedItemText
AccentColor
AccentColorText
While this list may be longer than the set supported in Internet Explorer, bear in mind the colors themselves may be duplicates. For example LinkText
and VisitedText
use the same color when WHCM is active (which was decided based on user feedback).
Browser Support
Unsurprisingly, each browser is going to have its own take on how best to support WHCM. With a proprietary start that is now moving down the standards track, support will continue to evolve.
Internet Explorer
Internet Explorer was the first to support the proprietary feature query. With some IE11 still in the wild, and given its historic support for WHCM, you may want to double up on your feature query and be careful of relying on background images.
Legacy Edge (Ledgacy)
The original version of Edge carried over the support from Internet Explorer with some adjustments. For example, in a later release it retained background images but added a backplate behind any text set over an image. With the browser nearly gone and Microsoft set to wipe it from hold-out computers in non-locked-down environments in April 2021, you can probably ignore it.
Chromium Edge (Chromiedge)
Microsoft has been building the standards-track support into Edge, and it is working. It also appears Edge still honors the proprietary media query, so you will want to be careful with the cascade when you use both.
Firefox
Firefox supports WHCM, but not the media queries and the media query. Be certain to close and re-open the browser after you enable WHCM, otherwise Firefox does not pick up on it.
8 June 2021: Firefox 89, released May 31, supports the forced-colors
media query (thanks to Nicolas in the comments for letting me know). There is more detail in the post Looking fine with Firefox 89 at Mozilla Hacks. Note that the images in this post use Firefox 85, before the feature query support existed.
Firefox does not support forced-color-adjust
, at least not through version 100. This will be a problem if you are counting on overriding how WHCM is applied.
Chrome
Nope. In fact, there is a bug where if you fail to set the page background, Chrome will use the WHCM window color which is often black. If your text is black (or not set), then your entire page is black.
See the Pen WHCM and Chrome Bug by Adrian Roselli (@aardrian) on CodePen.
Chrome 89
Chrome 89 supports High Contrast Mode. I can find no release notes that state this, but the change introduced in Edge 79 has seemingly made it into Chrome as of 89. The Chrome 89 beta release notes discuss the addition of forced-colors
detection and forced-color-adjust
support (Thanks to Šime Vidas for finding that) as well as the Chrome platform status notes.
Examples
I have taken a bunch of the stuff I covered and made some demos. I screen shat (shat is the past tense of shot) them in Firefox, IE11, and Edge. From experience, most WHCM users are not Firefox users, but they are still out there and rely on it working.
Backgrounds
Background images and gradients are treated slightly differently across the three browsers. Firefox sets a text backplate when there is a background image and dumps background gradients; it ignores any feature query overrides. IE11 sets no backplate for either, and dumps both background images and gradients unless you override it. Edge sets a text backplate on a background image, but dumps background gradients, overriding both if you do so in the feature query.
The following embedded pen shows the code, but you can test the debug version of the backgrounds pen.
See the Pen WHCM and Backgrounds by Adrian Roselli (@aardrian) on CodePen.
Inline SVGs
Inline SVGs grant you the ability to use CSS at the page level to manipulate their colors. While you can write feature queries into the SVG directly, when calling one inline you may want to handle it in your main stylesheet. In this example I have one SVG that uses currentColor
, so it should always inherit from the text. Two more have no colors defined at all, so they default to black, but for one of them I use the WHCM feature queries to set it to use GrayText
. The last one has its own colors defined throughout, so is not at risk and needs no overrides.
With Firefox and IE11, currentColor
is your friend (along with explicit colors). IE11 honors the feature query (GrayText
was just to show it in action). Edge takes it a step further and brings in the text color when no color is defined. Test it yourself in the debug version of this inline SVG pen.
See the Pen WHCM and SVGs by Adrian Roselli (@aardrian) on CodePen.
Added 9 November 2021: Melanie Richards gives some tips on papering over a (hopefully) short-term disparity between Edge and a CSS specification change:
The proper way to deal with this problem in the short term is to explicitly apply system colors to the SVG parts in forced colors modes. In this case, we would use the
LinkText
system color:
SVGs via <img>
s
If you have an SVG called via <img>
that generally follows a line-art style (icons, for example) then those are most at risk of disappearing completely if their color matches the WHCM window color. Granted, this is true with line-art transparent PNGs, but at least with Edge you can mitigate the effect.
In this example I use filter: drop-shadow()
in an effort to create an outline, albeit a faint one, on the first SVG. This is not an ideal solution. The third SVG file has a feature query to override its fill
from currentColor
to GrayText
, and both IE11 and Edge honor it. Give the debug version of SVG <img>
pen a test on your own.
See the Pen WHCM and SVG <img>s by Adrian Roselli (@aardrian) on CodePen.
Form Fields
Form fields will also take on a different look, but default form fields will do so in a predictable way. Because WHCM users will expect different field types in different states to look a certain way, it behooves you to know the defaults so you can mimic them in your own work — whether restoring styles you overrode or making a custom control look native.
The set of images below capture disabled, required, and error states. Notice how the placeholder field looks the same as the disabled field in IE11. Or how similar they are in Edge. Or the lack of an error style in Edge. Anyway, test the debug version of this forms pen as you see fit.
See the Pen WHCM and Form Controls by Adrian Roselli (@aardrian) on CodePen.
Custom Controls
Sadly, it is not uncommon for (terrible) developers to role-up a <div>
into a button. While that is rightly offensive, there are also plenty of controls that are not native to HTML, such as the oft misapplied tab. In each of the cases you want to look to the native (HTML or platform) implementation. Try to ensure custom controls give the appropriate visual cues in WHCM after all the fancy gradients and drop shadows and smells are stripped away.
In this pen I compare the styles of a native <button>
to a <div>
, and offer WHCM styles (proprietary and standards track) to try to reset them to native styles. I even included hover styles appropriate to the browser. You can, of course, test these fake buttons in the debug version of the pen.
See the Pen WHCM and Custom Buttons by Adrian Roselli (@aardrian) on CodePen.
Collected Examples
I gathered a few samples from above and made screenshots of them in Edge under each of the four themes I showed at the start of this post. Hopefully this reinforces the variety in display, and how using smart defaults will make your job easier. I left the Windows taskbar in there for context.
Wrap-up
Your job for WHCM users is to respect their color choices and use them appropriately. Do not override the feature because you may find something ugly. Ugly and usable trumps pretty and unusable every time.
To recap the tips:
- Ideally you should have to do little as a developer;
- Test across Firefox, Edge, and yes Internet Explorer 11 (for now);
- System color keywords work outside the feature queries;
- Match system color keywords to native OS use;
- Only override WHCM when necessary;
- Test your custom widgets in WHCM, and make it part of your definition of done.
References
- WHCM and Internet Explorer, bleeding a bit into Legacy Edge
- High Contrast Proof CSS Sprites by Steve Faulkner (January 2010)
- Windows High Contrast and Background Images by Terrill Thompson (December 2011)
- CSS Background Images & High Contrast Mode by me (August 2012)
- Windows High Contrast Mode: the limited utility of -ms-high-contrast by Patrick H. Lauke (December 2016)
- How to use -ms-high-contrast by Greg Whitworth (May 2017)
- Accessible SVGs in High Contrast Mode by Eric Bailey (June 2017)
- OS: High Contrast versus Inverted Colors by me (November 2017)
- Working with High Contrast Mode by Eric Bailey (October 2018)
- Quick(er) Note on ARIA and Windows High Contrast Mode by Scott O’Hara (February 2019, updated July 2022)
- WHCM and Legacy Edge (Ledgacy)
- Building a more accessible web platform by Bogdan Brinza & Rossen Atanassov (April 2016)
- SVG Filtering for Windows High Contrast Mode by me (March 2018)
- Working with the text backplate in Windows High Contrast by Greg Whitworth (August 2019)
- WHCM and Chromium-based Edge (Chromiedge), plus standards
- High Contrast Explainer by Rossen Atanassov & Alison Maher (January 2019)
- Finessing forced-colors: tailoring the High Contrast experience by Melanie Richards (September 2019)
- Quick Tips for High Contrast Mode by Sarah Higley (May 2020)
- Styling for Windows high contrast with new standards for forced colors by Melanie Richards & Alison Maher (September 2020)
- Added 1 October 2021: Using JavaScript to detect high contrast and dark modes by Scott O’Hara (October 2021)
- Added 22 March 2022: First Impressions of Forced Colors Emulation by Melanie Richards (March 2022)
Windows 11 HCM (5 December 2021)
Windows 11 is out and has updated this feature, both in name and color themes. Now rebranded as “Contrast Themes”, but still found under accessibility features, it better represents that not all themes are necessarily high contrast.
The feature query, how system colors are applied via CSS, and ability to customize them has not changed.
Since Windows 11 is still somewhat new and I know many are not upgrading to it yet, I have gathered screen shots of the four default themes. They show the configuration screen, the CSS system colors, and 4 of the samples from this post.
Bear in mind these themes are not as stark in default color choices (except maybe Night Sky) as in previous versions of Windows. I suspect some users may end up in them without understanding the implications for their experience across the web. As a developer, this may be more reason to avoid unintentionally creating a problematic experience for these users.
Emulation in Edge on macOS (8 March 2022)
As of Edge 98 on macOS you can emulate CSS forced colors mode, which so far only exists on Windows. In the dev tools, go to … → More Tools → Rendering. Then scroll down.
The limitation is that it only offers one color scheme. You cannot choose a low contrast scheme or set up one of the new Windows 11 contrast themes.
Emulation Thoughts (22 March 2022)
Melanie Richards wrote First Impressions of Forced Colors Emulation where she also hopes more themes will become available (for similar reasons as I have noted elsewhere).
I also added a link to her post in the References section above.
CSS4 Updates (13 July 2022)
The CSS Color Module Level 4 has been updated since I first wrote this post, adding 4 colors to the system color keywords. I updated the swatches in this post with the new ones.
WCAG Note, added 7 June 2023
I should have added this years ago since this post is my go-to reference for WHCM or whatever variation you are calling it.
WCAG question 623: Do issues with Windows high contrast mode fall under WCAG 2.1? from February 2019 says no, WHCM is not covered by WCAG:
The AG group appreciates that having customisations like High-Contrast-Mode (HCM) work properly are vital to many users.
However, WCAG 2.x does not explicitly address HCM. There are some failure techniques today such as failure techniques for pseudo content and CSS Background images as well as defining both foreground and background colors.
The place for more specification would be on the user-agent side of the equation, at least for the moment. Any criteria created for HCM could become rapidly outdated, possibly harmful if the user-agents change their behaviour.
If there were sufficient interest (i.e. volunteers) for creating a note or WAI-guidance page for authors, that is something we could tackle. It is also something that AG members could raise with vendors (e.g. Microsoft) to work with them to get more aspects of HCM publicly specified.
You can see the responses to the working group survey for additional feedback and thoughts.
The GitHub issue is still open since they might add a note about it to an Understanding document. Might.
Talk Reference (Added 7 July 2024)
I found this post referenced in a talk.
YouTube: Dessine moi un graphique (en CSS) by Gaël Poupard (in French)
6 Comments
From now on, people are undoubtedly going to think something’s wrong with me every time I hear someone use the term “screenshot” when I start laughing uncontrollably. I hope you’re happy.
Great post though, will share far and wide.
In response to .I am just glad I could maybe coin a new term. Thanks!
It seems that Firefox is now supporting the media query: https://www.mozilla.org/en-US/firefox/89.0/releasenotes/ (See “Web Platform” at the bottom of the release notes)
In response to .Post updated. Thanks!
Hi Adrian
> For example LinkText and VisitedText use the same color when WHCM is active (which was decided based on user feedback
Can you recall where this was decided?
In response to .Microsoft made this decision as explained to me by a Microsofter at an industry event where we were talking shop.
Leave a Comment or Response