high contrast applied to a graphics

Finessing forced-colors: tailoring the High Contrast experience

Windows High Contrast is an accessibility feature designed to increase legibility while decreasing cognitive load. Users can apply a High Contrast theme to view digital interfaces in a limited color palette, tailored to their desired level of contrast.

In this session you’ll learn how to optimize your styles for forced color modes—like High Contrast—using standards developed this year in the W3C CSS Working Group. Melanie will likewise cover some of the considerations that went into the design of these standards, and how they relate to other visual preference hints. See slides.


Video hosted by WebCastor on their StreamFizz platform.

photo of Melanie Richards

Melanie Richards, Program manager on Microsoft Edge

With a background in Web design and front-end development, Melanie helps to shape the Web platform as a Program Manager on the Microsoft Edge team. Melanie is a member of the ARIA, CSS, and WebApps Working Groups at the W3C, with a focus throughout on web accessibility. She loves a good side project and is currently pondering how we can bring more art and individual expression back to the Web.



Hi, everyone. As you heard, I'm a member of the Microsoft Edge web platform team and a member of several different groups here at the W3C, including the CSS working group.

So the CSS working group has been developing standards recently for integration with user system settings, such as Windows High Contrast.

So if you're unfamiliar, Windows High Contrast is an accessibility feature that helps to increase text legibility while decreasing cognitive load.

So the feature works by enabling a user to select theme colors and for a scoped number of semantic elements.

This scheme can then be applied to user interfaces and app content of reducing the visual complexity, while guaranteeing the user's chosen level of contrast.

So here's an example of Windows High Contrast set to a black theme.

As a description, the UI has been simplified into the chosen colors here.

So if you don't have a Windows machine, I'll share later on how you can experiment with this feature.

But in any case, like other apps, browsers can render their UI and even web content into the user's chosen color scheme.

So in parallel to bringing this to standards, I was actually recently a part of a usability study to determine how well High Contrast is working on the web for people.

So we had some folks who identify as having low vision, go through some websites with and without the High Contrast enabled.

So one individual remarked, "The text on the blue background is kind of hard to read." And so you might think that this person was reading something that was dark text on a dark background, like maybe a designer was trying to make some footer text more subtle or something.

But actually, they were referring to black text on a white background.

You cannot have a higher contrast ratio than this.

And yet, this person's eye's were picking up on that blue light and they still had trouble reading the text.

So we turned this into high contrast black, and the participant said, "Oh! That's much better!" this is actually the same exact contrast ratio as the previous slide, but it was easier for this individual to read.

So while we may try to provide reasonable defaults for our base styles, the truth is that needs for color and contrast vary from person to person.

These are highly contextual and can vary by the day or even the hour.

So maybe someone had an injury that makes it hard to look at screens, specifically, certain colors.

Or they find that a simpler color scheme helps them focus on the words.

Or maybe they're just staying up all night trying to finish some major project without keeping their partner up.

So the good news is, we can take a layered approach towards inclusion via coloring contrast on the web.

So emerging media queries and CSS properties enable us to respond to hints as to the users preferred color scheme and contrast as well as the presence of forced color modes like Windows High Contrast.

So with these new standards in hand, we can efficiently tailor our websites to users' visual needs.

But let's suppose that we're building out a marketing page for a service that sends you articles of clothing tailored to your individual style preferences.

So I'm gonna zoom in here a bit.

And our base brand is a light theme with cool colors.

We've got some mixed content here with a sample color pallette.

Some gradient photography.

Some decorative borders.

And some native form controls here at the bottom.

So there are a few related media queries that are involved here to shift this into different color schemes or contrast levels.

So the first of these is prefers-color-scheme which is a hint to provide a different color scheme based on user settings either from the browser itself or the operating system.

So these are things like light mode or dark mode.

In fact, the demo page that I showed a little bit earlier provides a dark blue color scheme whenever prefers color scheme dark evaluates to true.

So we won't step through this code today but I will have a link out to the demo at the end if you wanna poke through the code.

prefers-contrast is a hint to either increase or decrease a contrast.

And forced-colors is a hint that the web content is already rendered in the users' chosen colors.

And for example, when high contrast mode is active.

So there's a couple different expectations upon the web developer here.

For prefers-color-scheme and prefers-contrast, the expectation is that the web developer will fully manage the color scheme or contrast level.

And in forced-colors modes, these colors have already been applied and the website might just want to optimize for these color schemes.

So we don't have much time together today so I'll focus on how you can optimize for forced-colors modes.

But if you wanna learn more about these other standards, again, there's a link at the end of the slides.

All right, so let's dive into forced colors.

So standards around forced colors are heavily influenced by the Windows High Contrast feature that I shared earlier.

As well as the prior art used to style these in IE, and Microsoft Edge.

So it should be noted that Windows hight contrast is somewhat of a misnomer.

So while the inbox themes are certainly the most popular and do guarantee high contrast.

A user can actually set their colors to anything they want.

So if they actually want a lower contract level, or they want kinda disambiguate the colors from each other a little bit more, they are free to do that.

So, no matter the reason for choosing to use this feature it's actually one the most popular ease of access feature on Windows from far and away.

Last time we checked it was used on four percent of active devices, and that represents millions of people World wide.

So the OS setting provide the information needed to implement force color modes, but the onus is actually on the individual apps to make sure that their UI is rendered in the user's system colors.

So that means that the browser rendering engine is directly responsible for rendering web content in forced colors.

It also means that browsers could choose to implement forcec color modes directly in the browser themselves, separately from the OS, and Firefox does something of this nature today.

So let's take a look at our page in a forced color mode.

So we've set the a machine to a high contrast black theme.

And, without doing any work on the web development end, our page automatically pick up these colors.

So, the text is rendered in the text color from the color scheme, and the links are rendered in a separate semantic color, from the palette.

So these colors are shifted throughout our page, including native form controls.

So, how this works under the hood is that the rendering engine reverts a list of properties that are related, and other decorations that might interfere with text legibility.

So, the user agent then supplies its own style sheet which shifts the semantic element into the colors provided by the user color scheme.

So what's important to note here is that if you use any of these reverted properties to for example, denote state, you may need to make some adjustments in forced color modes.

And another interesting point to call out, is that background image is only reverted in user interactive controls, with the exception of buttons.

And so you may be wondering, well why not just globally revert background image?

So in historical implementations, this is actually something that we did.

But this way causes issues when CSS is used to render content images.

So for example, here is a feed of photos in one of these older browser versions.

Let the record show that you can't actually see any images whatsoever on this screen.

So how do we show background images, and also guarantee the legibility of text layered on top of those images?

The solution that we came up with in html, and which is now, well will be now, part of standards implementations is to render text backplates behind runs of text in forced color modes.

So no matter what the text is layered on top of, the users will always get their text in their preferred color scheme.

And so future standards may unlock the ability to style, tweak the styling of these backplates, such as changing the border radius.

A new detail introduced in standard implementations is that prefers-color-scheme also evaluates properly in forced color modes.

So the rendering engine use the Canvas color, or the page background color to determine if the color scheme is light or dark.

And then, it evaluates those media queries accordingly.

So actually, because our dark scheme shifted our gradients into a dark blue color, we're currently in a dark high contrast mode, and so you can tell that the gradients are also dark blue here.

So rendering engines can get pretty far by applying reasonable defaults based on semantics.

But individual web developers know their contents best, and so based on your expertise you can work on top of a platform to tailor the forced colors experience.

So let take a look at a couple ways to do that.

So, for example, our logo up here doesn't look so great in the forced color mode. It's still rendering in the dark blue, that was to original color.

And so, SVG can contain complex content, and as rendering engines we don't always know how we should render that in a forced color mode. So the only things that are color shifted, are text elements, and foreign object which embed html, and SVG.

So for single color SVG icon like our logo, we would want to set the source to fill current color, and this will inherit the user system color from the parent link.

We want to do this outside any media queries, because then, the inheritance can happen in any color mode, like light mode, dark mode, or forced color mode.

So you may have noticed that, when we shifted into this forced-color mode we lost some of the detail in the palette of our style profile. And so that's because we use background color to render these swatches.

So we could have shifted to a different strategy such as, using background images, or we can just manage the styles of this component ourselves.

So let review some component requirements in forced color modes.

We want to retain the color swatch.

We want to prevent that swatch rendering on top of any other user color, just in case it ends up looking a little bit muddy. So we always want to render that neither black or white. And we want to preserve the users color scheme for text legibility.

So let's start with our media query.

In previous browser versions, the syntax for this was -ms-high-contrast: adjust, and in standard this is now -ms-high-contrast: active.

And in standards this is now forced-colors: active.

So the CSS working group landed on this name essentially to future-proof this feature, we want you to be able, as Web developers to style for any forced color mode that exists in the future, not just high contrast.

So after setting up our media query, we want to unset the forced color from the element.

And so this strategy comes from the -ms-high-contrast: adjust CSS property.

In the new standards, forced-color-adjust set to none will remove the colors from the component and its children, and that includes any text backplates.

So our palette now looks as it did in dark mode with this CSS property applied.

And so now we'll want to render the background of the component in black, when we are in a dark forced color scheme.

And so we doing this again, because we don't want it to render on any random color, but actually we should be super careful with static colors in these kind of modes, and not try to color match to the user's scheme.

And the reason for that, is less obvious when we are in a black user mode, but when we shift into say a purple user color scheme, you can see that our static color isn't aware of the rest of the user's color scheme.

So we do want to make sure that that text is rendered in the user's colors.

So to do this we'll use the user's system colors to guarantee legibility.

So essentially creating our own backplate here, by setting the background color of the span to canvas, which is a page background, and the color to text.

So there are a few CSS system colors that are relevant when Windows high contrast is active.

System color help keep the styling manageable so that the correct colors are picked up no matter what, you can just write your CSS once in any user color scheme will look good.

So the updated set of colors that is relevant here also introduces the linktext color, which replaces the -ms-highlight value.

There is a full list of standardized list of system colors available on the CSS color editor's draft.

So not every operating system is going to support every single one of these colors, so it's important to test whenever you use these values.

Going back to our component, we actually want to change out that static background color in light color scheme to be white.

So in order to do this in the new standards we actually just combine media query conditions, so we have forced-colors: active, and prefers-color-scheme: light, and we can set that background to white here.

So in other considerations, we should be careful about using shorthand to remove styles.

So for example, in the forced color scheme, this button background and the page background color happen to be the same color.

So you can't actually see the bounds of this button, And that's because we set border to zero, in our base theme.

But, if you change this to border: 1px sold transparent, then it's invisible on the base theme, but you do get that border in force color modes.

So these standards are pretty new, so stable implementations aren't quite ready yet.

But, forced colors are in development within the Chromium project, and should ready to play with in preview versions Chromium based browsers pretty soon, And this is something that other browsers can implement as well.

So as I mentioned if you don't has a Windows machine there's a way to test, so in the short term, you can use virtual machines.

And in the future cross platform browsers could consider something in dev tools to spoof high contrast, or forced color modes, from directly within the tool.

So that would mean, you wouldn't need a Windows machine, or you wouldn't have to push your entire machine into a forced color mode.

Show of hands, like who would be interested in such a feature?

All right we got a couple hands throughout.

All right, so I hope you do get the chance to try out our content in forced color modes, because while browser rendering engines can provide reasonable defaults you are the expert on your web content, and can work on top of platform to deliver a truly well tailored experience.

So with these new standards in hand, let's design a more inclusive, and accessible web together.

Thank you so much, and you can find the demo, these slides, and all the resources at aka.ms/tpac-hc.

Thank you.