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.

CSS masks

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 background-image.

  .icon {
    background-color: red;
    -webkit-mask-image: url(icon.svg);
    mask-image: url(icon.svg);
}

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.

See the Pen SVG Mask by Noah Blon (@noahblon) on CodePen.

There are a bunch of properties related to mask, such as mask-position, mask-repeat, and mask-size, which align with CSS background properties. You can use the mask shorthand like the background shorthand:

  .icon {
    background-color: red;
    -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.

CSS filters

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.

  <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    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"/>
</svg>

  .icon-blue {
    -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 hue-rotate, invert, brightness, and saturation filters, I've created the ROYGBIV rainbow spectrum and some other basic colors like cyan and magenta.

See the Pen SVG Filtered by Noah Blon (@noahblon) on CodePen.

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.

Data URI

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.

See the Pen Sass-managed SVG Background-Image icons by Noah Blon (@noahblon) on CodePen.

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 color, stroke-color, and 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-size and background-position in your CSS, you choose which version to display. Here's how to set up an SVG sprite:

See the Pen JdojNv by Noah Blon (@noahblon) on CodePen.

Use the 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 width and 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 symbol and 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.

See the Pen 8a16bad16e744f88133c6a0d709d11ca by Noah Blon (@noahblon) on CodePen.

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.