I love using SVG in CSS background images but it sucks that you can't alter the
fill color easily within your CSS. Here are a few ways around that.
SVG in CSS backgrounds
Using SVG in CSS backgrounds allows you to use CSS's powerful background sizing and position properties. This makes sizing SVGs much simpler because the image easily scales to the size of your element. Plus you don't have SVG cluttering up your markup.
There are also some nice performance benefits over inline SVG. An SVG in a background image can be cached. Using image sprites and embedding SVG as a data URI can also improve performance.
This is my favorite method, but your browser support must be very progressive. With the
mask property you create a mask that is applied to an element. Everywhere the mask is opaque, or solid, the underlying image shows through. Where it’s transparent, the underlying image is masked out, or hidden. The syntax for a CSS
mask-image is similar to
Here I'm setting an SVG as the mask. The
fill of the icon in the SVG doesn't matter because it masks the background layer which is the color red. Therefore, the result is a red icon. For webkit, I'm using the prefix.
Your background can be a color, image, gradient -- whatever.
There are a bunch of properties related to mask, such as
mask-size, which align with CSS
background properties. You can use the
mask shorthand like the
-webkit-mask: url(icon.svg) no-repeat 50% 50%;
mask: url(icon.svg) no-repeat 50% 50%;
Masks are supported in most browsers. The IE team have CSS masks listed as under consideration. Firefox currently doesn't support external SVG masks.
You can apply Photoshop-like effects to DOM elements with CSS filters. Filters can be chained, with each filter acting on the result of its predecessor.
viewbox="0 0 24 24">
<path fill="red" d="M12 21.35l-1.45-1.32c-5.15-4.67-8.55-7.75-8.55-11.53 0-3.08 2.42-5.5 5.5-5.5 1.74 0 3.41.81 4.5 2.09 1.09-1.28 2.76-2.09 4.5-2.09 3.08 0 5.5 2.42 5.5 5.5 0 3.78-3.4 6.86-8.55 11.54l-1.45 1.31z"/>
-webkit-filter: hue-rotate(220deg) saturate(5);
filter: hue-rotate(220deg) saturate(5);
In this example, the icon has a pure red
fill set in the SVG. The
hue-rotate filter rotates the hue 220 degrees around the rgb color wheel. This makes the icon blue. The algorithm for hue-rotation isn't extremely accurate, so although the output should be pure blue it’s a little off. One way to fix this and boost up the color to full saturation is to add a
saturation filter. In the example, I added an arbitrarily large value of five to the chain, which increases the saturation by 500%.
By chaining filters together, you can make many colored icons from one colored icon input. With different combinations of
saturation filters, I've created the ROYGBIV rainbow spectrum and some other basic colors like cyan and magenta.
Creating a grayscale set of filters is pretty easy. You add a
grayscale filter and adjust a
brightness filter to the amount of gray you need.
This technique isn't super intuitive. It will probably require some trial and error to find the colors you need, especially since the algorithms aren't perfect. In the future, it would be fantastic if CSS filters could also work in HSL space, as they would be much more intuitive.
CSS filters are supported well in most browsers. IE has them listed as "In Development", which means they are in active development and should be added to IE soon.
As Chris Coyier demonstrated in his article, Probably Don't Base-64 SVG, properly formatted, you can pop SVG XML right into your CSS. Using this technique, and a bit of Sass magic, I've created some functions that allow you to dynamically change the color.
With this setup, add the path coordinates of your SVG to a Sass map with a key and invoke the function with your parameters. You call the function with the icon's name, which corresponds to the key in the map. You can pass in arguments for
stroke-width. You can also do other fun stuff like pass in any SVG valid CSS, as I did with the
stroke-dasharray in the last example.
With proper URL encoding, this will work in IE. Obviously its quite intricate to get right.
SVG Background Sprite
Creating sprites for SVG uses the same concepts as normal image sprites. The sprite contains all of the versions of an image. By manipulating the
background-position in your CSS, you choose which version to display. Here's how to set up an SVG sprite:
xmnls namespace attribute or the SVG won't work in your background. Also include the
xmlns:xlink attribute if using links, which I am in the
use tags. The
height need to be large enough to contain all of the images. In the example I'm using twenty-four 24x24 icons stacked vertically, so my SVG dimensions are 24x576 (24 times 24 = 576).
I'm using the
use tags to keep the file size low. Define the icon shape as a
symbol and place it in a
defs block. Give it an
id. Employ the
use tag to stamp out versions of this symbol. In the
use tag, the
y coordinate is adjusted so the icons stack on top of each other at 24 unit increments. The
fill attribute colors the icon. Here's a demo with a bunch of different colored icons defined using this technique.
I'm using Sass here to make the background positioning easier.
This technique works great everywhere SVG is supported. Because you need to manually create and add new icon versions to the sprite, it’s pretty inflexible.
Those are the methods I could think of for coloring an SVG as a background-image with CSS. Are there more? Probably!
Noah Blon is a web developer in Minneapolis, MN.