Icon System with SVG Sprites

I’ve been a big proponent of icon fonts. Lots of sites really need a system for icons, and icon fonts offer a damn fine system. However, I think assuming you’re good with IE 9+, using inline SVG and the <use> element to reference an icon is a superior system.

First let’s cover how it works.

A nice way to handle your icons is to have a folder full of .svg files.

That’s one of the cool things about working with SVG – they are the source files.

They can be colored, not colored, multiple shapes, sizes, whatever.

You can let Illustrator (or whatever) save it however, with all the cruft that comes along for the ride:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://ift.tt/IHuy5b">
<svg version="1.1" id="Layer_1" xmlns="http://ift.tt/nvqhV5" xmlns:xlink="http://ift.tt/PGV9lw" x="0px" y="0px"
	 width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
	<path d="M50.049,0.3c14.18,0.332,25.969,5.307,35.366,14.923S99.675,36.9,100,51.409c-0.195,11.445-3.415,21.494-9.658,30.146 - yadda yadda yadda"/>

Combine the .svg files

You can manually do this if you want. I’ve done it. You don’t even have to look at the final file. Just call it svg-defs.svg or something.

It should just be an <svg> tag, with a <defs> tag (which just means you are defining stuff to use later), and then a bunch of <g> (group) tags. Each <g> tag will have a unique ID, and will wrap all the paths and whatnot for each icon.


    <g id="shape-icon-1">
      <!-- all the paths and shapes and whatnot for this icon -->

    <g id="shape-icon-2">
      <!-- all the paths and shapes and whatnot for this icon -->

    <!-- etc -->


Again you can do that by hand, but of course that’s a bit laborious. Fabrice Weinberg has created a Grunt plugin called grunt-svgstore that automates this.

If you’ve never used Grunt, you can do it. Here’s a screencast to get you started.

You can install it with:

npm install grunt-svgstore --save-dev

Make sure the task is available with:


And then in the config:

svgstore: {
  options: {
    prefix : 'shape-', // This will prefix each <g> ID
  files: {
    'processed/svg-defs.svg': ['source/*.svg']

In the output file, svg-defs.svg, each icon (whatever paths and stuff from the source .svg file) will be wrapped up in a tag with a unique, prefixed ID, and the file name (minus the .svg). Like:

<g id="shape-codepen">

Inject that SVG at the top of the document

Literally include it, like:

<!DOCTYPE html>
<html lang="en">


  <?php include_once("processed/svg-defs.svg"); ?>

Or however you want to do that.

It’s gotta be at the top, sadly, as there is a Chrome bug in which this isn’t going to work if defined later.

Use the icons wherever

Now you can use them wherever! Like:

<svg viewBox="0 0 100 100" class="icon shape-codepen">
  <use xlink:href="#shape-codepen"></use>

Make sure you use those class names on the svg to size it.

/* Do whatever makes sense here.
   Just know that the svg will be an 
   enormous 100% wide if you don't 
   reign in the width. */
.icon {
  display: inline-block;
  width: 25px;
  height: 25px;

Yay: you can style them (and their parts) with CSS

One of the reasons we loved icon fonts is the ability to style them with CSS. This technique one-ups that in that we do everything we could there, and more, because:

  1. We can style all the separate parts
  2. SVG has even more things you can control, like special filters and strokes

The svg is (kinda) in the DOM, so JavaScript too. Here’s some styling possibilities and a demo of this all at work:

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

Browser Support

On the browser support front, the danger zones are IE 8 and down, Safari 5 and down, iOS 4.3 and down, and Android 2.3 and down. But if your policy is “the last two major versions” – you’re looking at pretty much 100% support.

Remember that icons can be used as a supporting role only, like always accompanied by a word. If that’s the case, support isn’t too big of a deal. If these are stand-alone, and non-display would make the site unusable, that’s a big deal.

I probably would go for icon fonts, as the support there is much deeper. Just make sure you do it up right.

This is going to get a lot better

Ideally we’d be able to do this:

<svg viewBox="0 0 100 100" class="icon shape-codepen">
  <use xlink:href="http://ift.tt/1nM9ZDX"></use>

I think it’s browsers intention to support that, I just haven’t seen it working yet. That would mean we wouldn’t need to include the inline SVG at the top of the document, we could just link out to it. Yes, one more HTTP request, but it would probably more efficient with browser caching and certainly less page cache bloating.

Browsers treat <use> like the shadow DOM:

Right now, we can target, say, an individual
with CSS, like:

.targetting-a-path {
  fill: red;

But that will affect all instances of that path. You’d think you could do:

svg.shape-version-2 .targetting-a-path {
  fill: red;

But that doesn’t work. It crosses that shadow DOM boundary. Ideally you’d use the “hat” selector to break that:

svg.shape-version-2 ^ .targetting-a-path {
  fill: red;

But that’s not supported yet either and it’s not entirely clear if that’s exactly how that will work or not.

“Versus” icon fonts

Vector-based: tie

Style with CSS: slight edge to SVG sprites (targeting parts, SVG specific styling like strokes)

Weird failures: SVG seems to just work (when supported). Icon fonts seem to fail in weird ways. For instance, you map the characters to normal letters, then the font loading fails and you get random characters abound. Or you map to “Private Use Area” and some browsers decide to re-map them to really weird characters like roses, but it’s hard to replicate. Or you want to host the @font-face files on a CDN, but that’s cross-origin and Firefox hates that, so you need your server to serve the right cross-origin headers, but your Nginx setup isn’t picking that up right, SIGH. SVG wins this one.

Semantics: Not a huge deal, but I think an <svg> makes a bit more sense for an image than a <span>.

Accessibility: Maybe someone can tell me? Can we/should we give the <svg> a title attribute or something? Or a <text> element inside that we visually hide?

Ease of use: Tools like Fontello and IcoMoon are pretty good for an icon font workflow, but the folder-full-of-SVGs with Grunt squishing them together for you is even easier, I think.

Ian Feather posted an article about why they switched away from icon fonts as well and I agree with every single point.

Icon System with SVG Sprites is a post from CSS-Tricks

from CSS-Tricks http://ift.tt/1nM9ZE9


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s