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.
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.
Interesting. Can this work somehow as well with SVGs that are loaded as background-images?
My guess would be anchors with pre-defined colours in the SVG document.
I’ve seen a trick like that before, where the file path was like svg.svg?color=#f00 and some JS inside the .svg ran and colorized itself.
That’s cool, though I’d be most interested in a non-JS solution
I don’t think there’s a pure HTML/CSS solution.
What about SVG used as a border image?
That would inherit the font color.
I don’t know if it’s really useful, though…
Niiice. Looks like
currentColor
works in IE9+ too (same as plain ol’ SVG), so this is a great use for that value. Just when I was convinced thatcurrentColor
was pretty useless, you prove me wrong. :) Thanks!Since fill: only affects svg, it fails w3.org css validation , should I be concerned about that???
No.
Awesome. Saw a sneak peak of this yesterday as I was putting together a new pen.
It’s a real shame that it doesn’t work with the external sprite method, though. If there was a way to keep SVG in an external file for caching, and have things like fill work on them, I’d be a very happy chappy.
As it is, I’m still going backward and forward about whether to use SVG inline with and keep all of the styling goodies, or external with and get caching.
I really appreciate you covering all this SVG stuff, Chris! You could write an entire book on it at this point.
Hi Chris,
I was wondering about putting an svg file in div and then make it responsive. I have used D3 (library) collision detection balls on the home page of http://topgravity.com/ but, the problem it that i can’t make the width and height of that svg equal to screen size. If i increase width and height, a very bad interface occurs at small screen. I want it responsive with screen size. Kindly, give me some suggestion if you can.
Great article, did add a gradient once within a logo in SVG format once, guess this goes beyond and offers some possibility for more experiments. Great trick.