Build Your Own SVG Icons

Originally published at:

Web fonts are an easy way to integrate a flexible icon system into a web project without sacrificing compatibility with legacy browsers. The technical process of building web fonts has also become much simpler since the arrival of online tools like Icomoon or Fontello.

But HTML5 has brought us an even more versatile way to use icons on web pages: SVG – Scalable Vector Graphics.

SVG basic features are now widely supported by almost all browsers (take a look at, so there are now far fewer reasons not to use it.

And if you need to give support to Explorer 8, there are some very easy fallbacks you can apply.

Drawing icons

This step is exactly the same you can read in my article about web fonts, take a look at it for more detail on preparing your icons.

When your SVG files are ready, you'll need a method to include them in your project.

Let's look at the options we have available.

Using the <img> tag

This is a very basic solution, and although it isn't really suited for our scope, it brings us some interesting considerations.

It requires only the simple img tag you've probably used with a thousand JPGs, GIFs and PNGs.

Loading an SVG with the HTML IMG tag

This is a very easy way to use SVG files; you can control the image size as required using width and/or height attributes, but you can't control color.

This technique is fully compatible with all modern browsers except IE8 (and older IEs) and early model Android phones. In some cases both width and height are required for a correct display.

IE8 fallbacks

There are many ways to provide legacy browser compatibility, if you need it. In each case, you'll need to provide PNG files to replace your SVGs.

Personally, I prefer a gracefully degrading technique that requires that all files use the same names and share the same path. It also requires Modernizr.

A few lines of javascript will do the trick:

if(!Modernizr.svg) {
	var imgs = document.getElementsByTagName('img');
	for(var i = 0; i < imgs.length; i++) {
		var  this_src = imgs[i].src;	
		if(this_src.match(/(\.svg)$/)) {
			imgs[i].src = this_src.replace(/(\.svg)$/, '.png');

This technique – and some variations – are covered in this article: SVG Fallback with PNG Images.

Another very clever solution has been described by Alexey Ten, and also addressed by Chris Coyier in his SVG Fallbacks article.

You can also load an SVG image using the object or iframe tags. Each provides a markup-only way to load fallback images:

<object data="svg_image.svg" type="image/svg+xml">
	<!-- the following image is displayed if browser can't load svg image -->
	<img src="fallback.png" alt="fallback image"/>

Take a look at my embedding SVG codepen for an overview of all current embedding methods.

Enhancing img tag with SVG linking

The basic usage of img for SVG files can be enhanced using fragment identifiers.

Fragment identifiers are a built-in SVG property: we can reference a SVG portion using a SVG view specification or addressing an SVG element by its <view> ID.

The first method consists in specifying a viewBox when loading a SVG file.

<img src="svg_file.svg#svgView(viewBox(x,y,w,h))"/>

Where x,y,w,h represent fragment coordinates from file origins (x and y) and fragment width and height (w and h).

For example, to show only the black horse from this chess pieces sprite (from Wikipedia Commons) you have to detect values just like in the scheme below:

It might remind you of the 'CSS image sprite' techniques that some sites use for their UI elements.

You can see the result here:

Continue reading this article on SitePoint

They look really nice, thanks for this, you never know, maybe I’ll need it some day :slight_smile:

Would you mind giving an explanation of what the “CSS sprite” technique actually does? Hard to evaluate it’s efficacy if all you do is say “upload, hit the button, download” …

CSS sprites is when you combine multiple images into one file, and then, by doing that, you only have that one HTTP request for that image file (instead of 50 or however many images yo ucombined)

Then to reference a particular image in that combined image file, you mess with background-position to only show the part you want.

The graphic below is the image sprite that Youtube has used.

As @RyanReese said, it means the user only needs to download a single graphic on first page load. Often it’s not the downloading that slows a page load, but the server-browser negotiation over delivering hundreds of tiny files. Sprites get around that bottleneck.

Sprites will hopefully disappear when HTTP/2 is widely adopted.
In the meantime, SVG sprites are actually a good alternative because you don’t need to use the background-position property to determine which sprite you want, thus being able to use that property again as intended.

So if you meant “Image Sprite” why did you give it a new name?

No wonder I was puzzled, I was trying to work out what was different between “Image Sprite” and “CSS Sprite” and there isn’t one!

It’s not a new name. More people call it CSS sprites (that I’ve seen) than image sprites.