SVG sprites

<svg>
    <symbol id="icon-envelope" viewBox="0 0 22 16">
        <path
            style="fill:none;stroke:#ffa3ea;stroke-width:1"
            d="M 18,2.5 h -16.5 l 10,8 10,-8 v 12 h -20 v -8"></path>
    </symbol>
</svg>

SVG, a Scalable Vector Graphics, is a mature technology. It is on the Web for a long time and is well supported across the browsers and is broad used on the Internet. Photos are the only image type that can't be replaced with SVG. Lets decide whether it is safe to get rid of raster sprites.

SVG sprites are different

Sprites allow us to use mininal HTTP requests for graphic elements and avoid awaiting for fetching new images when you try to change element's apearance on user interaction, for instance on pointer device events. SVG sprites are implemented in different technique, then te older raster sibling. Instead of putting a particular piece of oversized image into a limited viewport, you define a set of graphics elements to use them elsewere in the DOM. Look at the sample, taken from the social links you find at the bottom of the site.

Now lets see how its done.

Define the templates

Please look at the SVG node below.

Templates definition
<svg style="display:none">
    <symbol id="icon-fb" viewBox="0 0 16 16">
        <path
            style="stroke-width:1;fill:none;[...]"
            d="M 1.327921,0.5 C 0.8706167,0.5 0.5,0.8705 [...] z"></path>
    </symbol>
    <symbol id="icon-tw" viewBox="0 0 16 16">
        <path
            style="stroke-width:1;fill:none;[...]"
            d="m 11.546616,8.0162225 c 0.499719,0 0.929144 [...] z"></path>
    </symbol>
</svg>

The number of HTTP requests reduced to 0 (zero), because the element is built directly into the HTML page. Let's emphasize this second advantage over raster sprites (the first one is scalability, of course). Yes, I know one may built raster graphics to html with data URI too. If you rely on rasters, use this technique.

By the way, don't forget to style="display: none". Otherwise the element will occupy it's default area on the page, though won't draw anything, because the <symbol> element is not rendered in the document. The [id] attribute is mandatory, if you want to reference the template later.

Referencing templates

To use the graphic element defined by template, one must reference it in the following way:

Use of defined elements
<svg>
    <use href="#icon-fb" xlink:href="#icon-fb"></use>
</svg>

The <use> element refers to the <symbol> defined elsewere in the DOM. xlink:href is a legacy feature for support of SVG v1.1. Though the current v2 is widely supported, this few extra letters do not hurt me, so I keep duplicating the link for backward compatibility.

<symbol> vs <defs>

When you will search the Web on the topic you will find two ways of definition: with <symbol> and <defs>. Those guys who promote the latter, I think, just follow this advise, found in the linked above MDN page:

It is recommended that, wherever possible, referenced elements be defined inside of a <defs> element.

But I use the first one, because it is designed specifically for our purpose:

The <symbol> element is used to define graphical template objects which can be instantiated by a <use> element. The use of <symbol> elements for graphics that are used multiple times in the same document adds structure and semantics.

And also supports 2 useful attributes with self-speaking names: preserveAspectRatio and viewBox.

I also seen a combined approach:

<svg style="display:none">
    <defs>
        <symbol id="icon-fb" viewBox="0 0 16 16">
            <path
                style="stroke-width:1;fill:none;[...]"
                d="M 1.327921,0.5 C 0.8706167,0.5 0.5,0.8705 [...] z"></path>
        </symbol>
        <symbol id="icon-tw" viewBox="0 0 16 16">
            <path
                style="stroke-width:1;fill:none;[...]"
                d="m 11.546616,8.0162225 c 0.499719,0 0.929144 [...] z"></path>
        </symbol>
    </defs>
</svg>

But can't justify this from what I read in the MDN docs or elsewhere on the web.

Summary

Advantages

To summarize, I don't see any area where raster sprites have advantage over SVG. I assume you don't code for IE < 9. Do you? Oh dear, my compassion... For the rest of us we have:

  1. a scalable images for all screen resolutions
  2. 0 (zero) additional HTTP requests number

So far so good. Any limitations?

Limitations

I love SVG not only for scalability, but also for the ability to modify it's DOM and animate these modifications. See, how the bars of menu trigger are crossing?#1

Lets make some eye-candies for our social links icons... Wait... Maybe wrong css selector or something... No, it just doesn't work :(

Why? There is a good reason for it. When you <use> some element you don't have access to it's <symbol> subtree. Think of your icon not like a separately instantiated object, but like a mirror of it's template. And you have no acces with CSS to that prototype, and no event you trigger on the used reflection is triggered for the prototype either. Frankly, how I imagined to manipulate the prototype's subtree and expect NOT to see these changes in every of reflections? OK, one just have to accept it. If you need to manipulate the SVG DOM, you need to have an independent SVG node.

While this is definitely a limitation, it is such only when compared to a separate SVG node, not to raster sprite. When compared to rasters, the boundaries are only extended.

If you have any questions, suggestions, corrections or objections etc, please contact me, until I make a comments under articles.

Thank you for reading!

#1 One may see the animation in Chrome. FF Nightly was animating d attribute of the <path>, but changed the behaviour later