Build Your Own SVG Icons

Massimo Cassandro
Massimo Cassandro
Share

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 caniuse.com), 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.

A collection of SVG files

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">
</object>

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:

Viewbox coords for Black horse

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

You can see the result here:

See the Pen svg img + fragment identifier by Massimo Cassandro (@massimo-cassandro) on CodePen.

The second way requires that the SVG contains a specific <view> of our fragment.

If our Chess Pieces file contained something like this:

<view id="black-horse" viewBox="140 52 34 33" />

We could obtain the same result using:

<img src="Chess_Pieces_Sprite.svg#black-horse">

Both methods are compatible with all major browsers (including IE9 +), except IOS devices that don’t correctly display the “view” method fragments. Happily IOS is fine with the first method.

All browsers require that the image is explicitly sized (with width and height attributes or CSS rules) to be displayed correctly.

For more info on SVG linking take a look at:

More sprites

Until now, we’ve seen nothing that makes SVG an obvious replacement for web fonts – but we can do much more with SVG. We can arrange our SVG icon files to construct a much more flexible and powerful tool.

There are three main ways (that I know) to do this:

  1. Simurai SVG stacks
  2. CSS sprite
  3. Using SVG <defs> and <symbol>

Simurai SVG stacks

This is the first method that I became aware of, and I think it’s fair to say that it’s relatively outdated today. Nevertheless, I do want to mention it, if only for the record.

This technique was first described by Simurai at his blog in 2012, though I read of it at SitePoint too.

As you can see in the screenshot below, this technique requires that all your symbols stack on top of each other – not unlike Photoshop layers. Each of them has the same class (icon) and a unique ID.

SVG stacks in Brackets

The SVG contains the following CSS.

<defs>
    <style>
        .icon { display: none; }
        .icon:target { display: inline; }
    </style>
</defs>

All icons will disappear until they’re invoked using the fragment identifier syntax:

<img src="icon_file.svg#spriteID">
SVG stack file

Using the img tag, this technique works well with Firefox, Chrome, Safari (desktop) and Opera. However it doesn’t work with any IE browsers or IOS devices.

You can use SVG stacks with background images too (adding some CSS to your page) but this unfortunately only works with Firefox.

CSS sprite

This technique has been refined by Filament Group and consists in a web application (or a Grunt plugin if you prefer).

Grumpicon web app

As you can see at the Grumpicon page, “the tool processes a set of SVG files, generates PNG fallback images for legacy browsers, and exports a demo page showing how to use the final icons”.

I’ve created a demo on Codepen (removing the fallback script), and this is the result:

See the Pen Grumpicon demo by Massimo Cassandro (@massimo-cassandro) on CodePen.

This is a production quality, ready-to-use technique. I’ve tested it in all major browsers (including IE8) and it works flawlessly in all them.

We can also use CSS sprites with an external SVG file, as we’ll see below.

Using SVG <defs> and <symbol>

The last method is the one I personally prefer, and it’s well explained in a CSS-Tricks article.

It uses the svg tag as a wrapper in which every icon is described into a <defs> or <symbol> tag.

<svg>
	<defs>
		<g id="icon1">
			<!-- icon shape here -->  
		</g>
	</defs>
	<symbol id="icon2" viewBox="0 0 100 100">
		<!-- icon shape here -->  
	</symbol>
</svg>

Icons are displayed by the <use> tag:

<svg viewBox="0 0 100 100">
	<use xlink:href="#icon1" />
</svg>
<svg>
	<use xlink:href="#icon2" />
</svg>

You can see that, since the symbol tag has its own viewBox attribute, you don’t need to set it every time the icon is displayed, which makes this method very easy to use.

The collection of symbol tags can be built manually, using some Grunt plugin (google for Grunt SVG merge) or, once again, with Icomoon.

Icomoon app

After your icons have been uploaded to the Icomoon app, choose the glyphs you need and, instead of generating a font, click the Generate SVG/PNG button.

You can also set some preferences to generate PNG fallback files too and even an old-style CSS sprite (both for PNG and SVG files), just like in the CSS sprite chapter. Note that the sprite files generated by the Icomoon app, make the creation of an almost pure-CSS fallback very easy.

Icomoon preferences

The download button will then deliver a collection of files, including a ready-to-use SVG file with perfect <symbol> definitions built into it.

Here’s the result:

See the Pen SVG symbols demo by Massimo Cassandro (@massimo-cassandro) on CodePen.

This method works fine in all major browser including IE9+, but, since the combined SVG is embedded in the page, there’s no way of caching it in the browser.

Luckily, we can reference the SVG symbols from an external file. In this case the syntax becomes:

<svg>
	<use xlink:href="external_file.svg#iconID" />
</svg>

This method works in all major browsers, except for IE9+. However Jonathan Neal’s SVG4everybody script can even solve this problem, as is clearly explained in SVG use with External Source.

Resources

I think there are lots of exciting possibilities around these ideas. If you’re interested in learning more, here are some resources I’ve found very useful:

Frequently Asked Questions (FAQs) about Building SVG Icons

What are the advantages of using SVG icons over other formats?

SVG, or Scalable Vector Graphics, offer several advantages over other formats like PNG or JPEG. Firstly, SVGs are resolution-independent, meaning they can scale to any size without losing quality. This makes them perfect for responsive web design. Secondly, SVGs are typically smaller in file size, which can improve website load times. Lastly, SVGs can be styled and animated with CSS and JavaScript, providing more flexibility and interactivity.

How can I create my own SVG icons?

Creating your own SVG icons can be done using vector graphic software like Adobe Illustrator or Inkscape. These tools allow you to design and export your artwork as SVG files. Alternatively, you can write SVG code manually using a text editor, although this requires a good understanding of SVG syntax.

Can I use SVG icons for commercial projects?

Yes, SVG icons can be used for commercial projects, but it’s important to check the licensing terms of any icons you download from the internet. Some may require attribution or have other restrictions. If you create your own SVG icons, you can use them however you wish.

How do I add SVG icons to my website?

There are several ways to add SVG icons to your website. You can embed the SVG code directly into your HTML, use an img tag, or use CSS background images. Each method has its own advantages and considerations, so choose the one that best fits your needs.

Why are my SVG icons not displaying correctly?

If your SVG icons are not displaying correctly, there could be several reasons. The SVG code might have errors, or the icons might not be compatible with certain browsers. It’s also possible that the CSS styling is interfering with the icon display. Check your code and browser compatibility to troubleshoot the issue.

Can I animate SVG icons?

Yes, SVG icons can be animated using CSS or JavaScript. This allows you to create interactive effects like hover states, transitions, and transformations. However, keep in mind that complex animations can impact website performance.

How can I optimize SVG icons for better performance?

Optimizing SVG icons can involve several steps. You can minify the SVG code to reduce file size, remove unnecessary metadata, and use CSS for styling instead of inline attributes. Additionally, consider using SVG sprites to combine multiple icons into a single file.

Can I use SVG icons in email newsletters?

While SVG icons can technically be used in email newsletters, support varies across different email clients. Some clients may not display SVGs correctly, or at all. Therefore, it’s generally safer to use PNG or JPEG images for email newsletters.

How can I convert other image formats to SVG?

Converting other image formats to SVG can be done using vector graphic software or online conversion tools. However, keep in mind that raster images like PNG or JPEG may not convert well to SVG, as they lack the vector data necessary for smooth scaling.

Are there any resources for free SVG icons?

Yes, there are many resources for free SVG icons online. Websites like SVGRepo, Flaticon, and IconSVG offer a wide range of icons for different purposes. Always check the licensing terms before using these icons in your projects.