Making single color SVG icons work in dark mode

In a project I work on, we had a couple of buttons that consisted of just icons (with visually hidden help text). The QA engineer I worked with, found some of those did not show up in dark mode, which rendered the buttons unusable for users of that mode. Using inline SVGs with currentColor fixed the issue.

What’s dark mode?

Dark mode (similar-ish to high contrast mode) is a setting on platforms, browsers or devices that inverts a user’s colour scheme: from dark elements on a light background to light elements on a dark background.

This setting improves the experience for all sorts of users. For instance, people who work in the evening, those spend a lot of time behind their screens and users with low vision. It also saves energy on some types of screens.

Dark mode is available on the latest macOS and Windows 10, but also in the form of a browser plugin (Dark Background and Light Text add-on for Firefox, Dark Night Mode Chrome extension). In this post I’ll refer to Dark Modes as one thing that generally works the same across different implementations. In reality, there can be inconsistencies, of course. They can be tricky to test remotely, as testing platforms like Browserstack don’t support dark modes for security reasons.

Some dark modes will flip colors on existing websites, turning your white colours black. In our project, we try to make our interface work with that kind of dark mode, as some of our users use these settings and it lets them have a much better experience. This is a relatively cheap accessibility win.

Inline SVGs to the rescue

Let’s assume our site has a light background with black icons. One way to include an SVG icon is to use an <img> tag pointing to the SVG. Here’s an example of a chevron icon:

<img src="chevron-right.svg" alt="" aria-hidden="true" role="presentation" />

(examples on CodePen)

In Windows High Contrast, Dark Background and Light Text and Dark Night Mode, the icon simply did not show. I believe the reason is that Dark Modes generally parse style sheets only, they ignore the contents of markup (including SVG files). In those cases, they will not replace black with white.

If we could only set the color for these SVGs in our stylesheets! Well, currentColor allows for that, and, it turns out, that actually works with Dark Modes:

<svg
  xmlns="http://www.w3.org/2000/svg"
  width="24"
  height="24"
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
> 
  <polyline points="9 18 15 12 9 6" />
</svg>

For those new to currentColor: it resolves to whatever the CSS color is (as set or inherited) of the element the svg is used in. So if a tool updates all colors in the page, the SVGs automagically change colour too. It is also popular because it works great with states like hovers: for icons with text, icon colours will change whenever you change the text colour.

Declaring supported color schemes

After I posted this, Amelia Bellamy-Royds helpfully pointed me at a proposal for declaring color schemes preference. It is proposed to be a property you can set at root level (supported-color-schemes: light || dark) or as a meta tag, so that browsers can be in the know before they start parsing CSS. The property basically lets you tell a browser that your CSS supports dark modes and will not break in them. Safari has experimental support for the property in Technology Preview 71.

The supported-color-schemes property is meant to be used in conjunction with the prefers-color-scheme media query.

Conclusion

So, if you use currentColor for the only (or primary) colour in your SVG icons, they will work better in dark modes. I’ve not done much more research than this, but hope it helps others who try to make their icons work in dark mode. Feedback more than welcome!

Update 25-12-2018: added section about declaring color schemes.

Thanks Šime Vidas, Amelia Bellamy-Royds and Timothy Hatcher for their feedback and suggestions.

Comments, likes & shares (39)

cool! is it possible to determine whether the user's machine is currently in dark mode in css or js? that'd be rad
sweeeeet!
@hdv heb jij wel eens meegemaakt dat je een font alleen voor 1 header gebruikt (bijv een logo)? wat is de beste oplossing? converteren naar svg en embedden? of is dat niet echt accessible?
Hidde wrote on 24 December 2018:
yes! with `@media(prefers-color-scheme:dark)` developer.mozilla.org/en-US/docs/Web…
Šime Vidas wrote on 24 December 2018:
Using currentColor makes sense in general, but is this really related to dark mode in macOS? I use it, but it doesn’t seem to affect the currentColor value in Safari (which remains black):

https://output.jsbin . com/vumedoc/quiet
Hidde wrote on 24 December 2018:
I think it is specifically the best bet when dealing with systems that automatically make websites dark, I think Safari doesn't do that yet. Maybe I should clarify in my post
Amelia Bellamy-Royds wrote on 25 December 2018:
By the way, for color overrides that truly operate at the browser level (like Windows high contrast mode), the `currentColor` approach will work in stand-alone SVG in <img>, too, since the default `color` will have changed.

But no guarantees with JS/extension-based dark modes.
CSS-Tricks wrote on 29 December 2018:
> if you use currentColor for the only (or primary) colour in your SVG icons, they will work better in dark modes.

hiddedevries.nl/en/blog/2018-1…
Andrea Giammarchi wrote on 29 December 2018:
... and Linux (GNOME) for the last 5 years ... but people gotta ignore it, 'cause it's still cool in (soon) 2019 to ignore Linux, same cool as it's been ignoring Firefox, or MS Edge, 'till now ...

hiddedevries.nl/en/blog/2018-1…
Roberto Iriondo wrote on 29 December 2018:
> if you use currentColor for the only (or primary) colour in your SVG icons, they will work better in dark modes.

hiddedevries.nl/en/blog/2018-1…
Jeremy Keith wrote on 29 December 2018:

Another good reason to use the currentColor value in SVGs.

DAI Builds - Digital Agency wrote on 29 December 2018:
@robiriondo: > if you use currentColor for the only (or primary) colour in your SVG icons, they will work better in dark modes.

hiddedevries.nl/en/blog/2018-1…
Adactio Links wrote on 29 December 2018:
Making single color SVG icons work in dark mode hiddedevries.nl/en/blog/2018-1…
Resoource wrote on 31 December 2018:
Making single color SVG icons work in dark mode hiddedevries.nl/en/blog/2018-1…

#CSS #SVG #webdev #code #FrontEnd
Stéphanie Walter wrote on 2 January 2019:
"Making single color SVG icons work in dark mode" in-line SVG + currentColor +
supported-color-schemes in conjunction with prefers-color-scheme
hiddedevries.nl/en/blog/2018-1…
David liu wrote on 2 January 2019:
RT WalterStephanie: "Making single color SVG icons work in dark mode" in-line SVG + currentColor +
supported-color-schemes in conjunction with prefers-color-scheme
hiddedevries.nl/en/blog/2018-1…
Front-End Front wrote on 3 January 2019:
Making single color SVG icons work in dark mode hiddedevries.nl/en/blog/2018-1…
julzmon wrote on 4 January 2019:
Making single color SVG icons work in dark mode hiddedevries.nl/en/blog/2018-1…
Sean Goresht wrote on 7 January 2019:
Making single colour #SVG icons work in dark mode - hiddedevries.nl/en/blog/2018-1…
Sean Goresht wrote on 7 January 2019:
Making single colour #SVG icons work in dark mode - hiddedevries.nl/en/blog/2018-1…
Dany wrote on 10 January 2019:
Making single color SVG icons work in dark mode hiddedevries.nl/en/blog/2018-1…
Dan Q wrote on 29 December 2018:

In a project I work on, we had a couple of buttons that consisted of just icons (with visually hidden help text). The awesome QA engineer I worked with, found some of those did not show up in dark mode, which rendered the buttons unusable for users of that mode. Using inline SVGs with currentColor fixed the issue.

This is neat. I’m not yet convinced of how wise it is for an operating system preference (dark mode) to be exposed via its browser, but I can see the logic. And I approve of the fact that CSS can be used to interrogate it. But really what I like about this article is the demonstration of how currentColor propogates even into inline SVGs: that’s neat, and a good observation by the author of the linked article.