Cascading SVG Fill Color

Avatar of Chris Coyier
Chris Coyier on (Updated on )

DigitalOcean provides cloud products for every stage of your journey. Get started with $200 in free credit!

One time someone told me their biggest problem with SVG icons is that they didn’t match the color of text they were by. In fact it was such a big problem for them, that despite seeing the advantages of SVG icons they were sticking with icon fonts. I didn’t think of it at the time, but there is a pretty easy solution for this.

The idea is to use the currentColor value in CSS to pass that text color through to the SVG shapes. For instance:

<h1>
  <svg viewBox="0 0 32 32">
    <use xlink:href="#icon-phone"></use>
  </svg>
  Call Me
</h1>
h1 {
  color: blue;
}
h1 svg {
  fill: currentColor;
}

You can simplify this and let the fill cascade to the SVG:

h1 {
  color: blue;
  fill: currentColor;
}

So fill cascades eh? Pretty neat. Why don’t we just do this then if it’s that easy:

body {
  fill: currentColor;
}

fill only affects SVG anyway, so it won’t be doing anything we don’t want it to do, and it’s easily overridable by a more specific selector anyway.

The trouble is that doesn’t quite work as is.

Take this example, which is just our original example inside the <body>:

<body>
<h1>
  <svg viewBox="0 0 32 32">
    <use xlink:href="#icon-phone"></use>
  </svg>
  You'd think the SVG would fill blue too?
</h1>
</body>

Then:

body {
  fill: currentColor;
  color: red;
}
h1 {
  color: blue;
}
svg {
  border: 5px solid currentColor;
}

What is the currentColor at the <svg>? blue, right? Because color cascades (is inherited). We can see that’s true, because the border on that svg will be blue. But the icon itself (which is really a drawn <path>) will be red.

Weird, I think.

Update: Works (properly?) in Chrome now. Firefox and Safari still show the strange red fill.

It’s not a huge deal though, because you can just:

svg {
  fill: currentColor;
}

And that will ensure it snags the color from whatever you would normally expect it to. You can also apply the fill to the use, path, symbol, circle, rect, etc, but hitting the svg just kinda covers it all (which is nice for simple one-color use cases).

See the Pen lcDBd by Chris Coyier (@chriscoyier) on CodePen.