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:
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 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.
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! 🖤