Skip to main content

CurrentColor SVG in forced colors modes

Note: this post assumes familiarity with forced colors modes styling and Windows High Contrast, now called “Contrast Themes” in Windows 11. Refer to “Styling for Windows high contrast with new standards for forced colors” for a primer.

If you’ve been optimizing your web content for various color modes for some time, you may be familiar with using currentColor as an efficient way to manage single-color SVGs. Traditionally, setting currentColor to the strokes and fills of SVG parts…

Visit the Pen Forced Colors: Simple SVG Demo by Melanie Richards (@somelaniesaid) on CodePen.

…has meant that those SVG parts automatically inherit the SVG parent’s color value in the active color scheme. This has been true for your developer-provided light and dark modes styles, as well as forced colors modes such as Windows High Contrast:

The logo from the example, automatically rendered in light mode (a dark blue), dark mode (a light blue), and Windows High Contrast (the user’s link color)

The SVG logo in a light color scheme, dark color scheme, and Windows high contrast as a result of using currentColor.

If you’ve tried to use this technique in the past few months and found that your SVG appeared “broken” in Windows High Contrast mode on Chromium-based browsers (i.e. the SVG is not rendering in a forced system color), don’t worry—you are not imagining things.

The described currentColor technique was broken by a CSS specification change, in which the CSS Working Group decided that forced color values should be applied at used value time. Previously, they were applied at computed value time. I was not active in the CSS WG during this period, so can’t comment from firsthand experience, but it appears the change was made in large part to help clarify how animations and transitions behave in forced colors modes. currentColor, when used in the color property, inherits its parent’s computed color value. So, this spec change means that the SVG would inherit whatever that parent’s color was before forced color values were applied to web content.

Because the Chromium implementation was updated to match the spec*, the logo example currently looks like this in a dark Windows High Contrast theme in MS Edge v96:

The logo from the example, which is rendered in a light blue shade on top of a dark background, but it doesn’t match the bright blue shade of the system link color

The logo in this example is as least still visible, because we have provided a dark mode theme with prefers-color-scheme: dark, and the SVG is inheriting the light color we’ve used for the link in our dark mode styles. However, it would be better for this logo to pick up the system link color in forced colors modes, so that 1) it is rendered in the user’s chosen link color, with their preferred level of contrast and 2) the user knows that this is part of an invokable link target.

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:

View the Pen Forced Colors: Simple SVG Demo [CurrentColor Temporary Fix] by Melanie Richards (@somelaniesaid) on CodePen.

The logo now picks up the proper system link color in Windows High Contrast.

So, this works, but it’s certainly not as convenient as using currentColor and having the right color propagate automatically across color modes.

Thankfully, Amelia Bellamy-Royds brought up the issue again, and the CSS WG arrived at a solution to restore this common currentColor technique and heal currently-broken experiences. The spec now defines a preserve-parent-color keyword value for forced-color-adjust:

In forced colors mode, if the color property inherits from its parent (i.e. there is no cascaded value or the cascaded value is currentColor, inherit, or another keyword that inherits from the parent), then it computes to the used color of its parent’s color value.

In all other respects, behaves the same as none.

Because currentColor inherits the used color in this case, and forced colors are applied at used value time, it would now inherit the parent’s forced system color value.

This is effectively a direct fix for ensuring that SVG parts with currentColor inherit the correct user-defined system color in forced colors modes. Web developers would not need to use this keyword directly, as it will be applied to SVGs by default in the user agent stylesheet:

@namespace "http://www.w3.org/2000/svg";
svg|svg { forced-color-adjust: preserve-parent-color; }
svg|foreignObject { forced-color-adjust: auto; }

This replaces a user agent stylesheet rule where forced-color-adjust is set to none on SVGs.

Once this change lands, web developers should be able to use the currentColor technique once again to their hearts’ content (perhaps keeping the explicit system colors around for a bit, for compat on 2021 browser versions). At time of writing, this patch is in active development in the Chromium code base, so my hope is that this all resolves soon. In the meantime, use system color keywords for SVG parts in forced colors modes, and thank you for testing in Windows High Contrast! 🖤


*Firefox’s forced colors implementation does not appear to have the described issue, i.e. currentColor SVG parts inherit forced colors as expected. As far as I can tell, this appears to be because the Gecko implementation has not yet made the change to apply forced colors at used value time. Folks on the Mozilla team would be better positioned to clarify!

Responses

My blog uses Webmentions. Responses from sites which likewise support Webmentions, such as Twitter or people’s personal sites, will show up here.

  • Hidde on

    “If you’ve tried to use this technique in the past few months and found that your SVG appeared “broken” in Windows High Contrast mode on Chromium-based browsers (…) don’t worry—you are not imagining things.”—@soMelanieSaid melanie-richards.com/blog/currentco…
  • Reply from Sara Soueidan on

    Yep I've come across this a while back and updated course content to use canvasText for a demo I had. CSS system keywords are more reliable for this kind of "theming" anyway.
  • Reply from JulieG on

    Thankyou so much - I was starting to think I’d just dreamed that currentColor used to behave well!
  • Adrian Roselli 🗯 on

    Looks like I have a post to update.
  • Reply from Heather on

    This is very helpful! Thank you for writing it up. 🙂
  • Pablo Lara H on

    CurrentColor SVG in forced colors modes by Melanie Richards @soMelanieSaid #css #SVG #currentColor #webdev melanie-richards.com/blog/currentco…
  • Reply from Melanie Richards on

    Of course! Realized from our discussion the other day that this is probably a good one to capture top-to-bottom in a post, so thanks for the discussion!
  • Reply from Heather on

    It’s very helpful to understand what changed and how it is being fixed. Also, I’m super glad to not have to try to explain this since you wrote up the whole issue! 🙂 You’ll be getting a should out in my web directions preso and latest article on a11y svgs. 💯
  • Reply from Melanie Richards on

    Having a resource to point to is my goal for blogging! Thanks for the kind words and glad the post is helpful 😊
  • Adrian Roselli 🗯 on

    I *finally* added @soMelanieSaid’s post on SVG & WHCM to my WHCM post as an update: adrianroselli.com/2021/02/whcm-a… But go read her full post: “CurrentColor SVG in forced colors modes” melanie-richards.com/blog/currentco… I look forward to the fix.