A journal and wiki, of sorts, by yours truly

Colored SVGs with CSS

I was recently helping my good friend Luke with some design changes that he was making to his product, Exposure. Luke was lamenting that he was still using an icon font1 and not SVGs for simple graphics. Fonts allow him to move quickly with design changes and don’t require him to litter up his HTML with embedded SVG code, he said. I told him about a technique that I’ve been using recently—including on this website—to use xlink:href to link an SVG file while still having the ability to change the color of the graphic with CSS.

The Problem

Changing the color of a graphic is one of the most significant benefits to using vector formats, but why would you want to change an SVG color in the first place? Think of all of the small symbol icons that we use to give extra meaning to things within our designs. Next to a phone number, you might display something like a telephone icon, or an envelope next to and email address, or perhaps a question mark near a link people visit to get help. Besides, many companies logos’—Apple, for example—are defined more by their shape rather than the color they are portrayed in. A single, scalable version of a symbol that can be used across a website in many different colors can be great for simplicity and maintainability.

SVG is a wonderful format in that is well supported across all modern browsers. Graphics represented as an SVG can be embedded directly in HTML and, after that, can have any number of manipulations or transformations applied to them. In addition to embedding the code directly into the markup of a website, SVGs can be used as you do other image formats. This means you can use them as a background-image in CSS and even by our humble friend, the <img> tag. While you can still resize and scale a graphic when linking to an SVG in CSS or HTML—as opposed to embedding to it directly—the problem is that, in doing so, you lose the ability to manipulate it and do things like change its color.

So, why not just embed the SVG directly into the HTML? You often can. Embedding works well for graphics that are a one-off like a chart within an article or an example graphic within a tutorial. But for something displayed multiple times across a website, like, for instance, a logo or link in the header and footer of every page, it can end up being a subtle instance of bandwidth creep to the SVGs embeded on every single page. Although SVGs are small in size, why ask visitors to your website to download the same code for the same image multiple times? Browsers are certainly capable of downloading it once and then referencing the file any other time that you link to it, instead of downloading it all over again.

What To Do

Within the SVG spec lies the simple <use> tag. This tag is commonly used to repeat something in an SVG document, for instance, something like a pattern. But, by using the xlink:href2 attribute, we can use the tag to reference something that lives within another SVG file. Here is what that looks like, in its simplest form:

<svg>
  <use xlink:href="/graphic.svg#identifier"/>
</svg>

What this does is pull in the external SVG file and virtually embed it inside the SVG tag that lives in the HTML. Now this SVG is capable of being styled by CSS. One thing to note is that the <svg> tag in your external file will need to have an id attribute on it in order for the <use> tag to be able to reference it. That is what we’re referencing when we put #identifier after the file name above. For instance:

<svg id="identifier">
  <circle cx="10" cy="10" fill="currentColor" r="20"/>
</svg>

Now that we have a <svg> tag within our HTML referencing and external SVG file, all we need to do is change its color. The other important bit in the code above that I haven’t mentioned yet is the currentColor value. You can use this value anywhere that you would typically use a standard color value (e.g., #00f) and the browser will use the current text color. This means that you can change the color of the SVG by using plain-old CSS:

svg {
  color: blue;
}

As you can see, linking to an SVG file this way is not any more complicated than using a simple <img> tag. It’s just a few new tags and attributes. But what about accessibility and older browsers? In my next article about SVGs, we’ll go over how to make sure these images can have graceful fallbacks.