Grunticon 2 is out! It’s got a cool new website. Grunticon is a damn fine tool for building an SVG icon system. The workflow is like:
- Have a folder full of SVG icons
- Run Grunticon on that folder, which produces everything you need
- Put the bit of JavaScript in the
<head>
- Use HTML like
<div class="icon-image"></div>
where you want icons - Icons everywhere!
Grunticon 2 even has a method for injecting inline <svg>
, so that you have all those advantages, like scripting, animating, CSS control, etc. You just add an attribute:
<div class="icon-burger alt" data-grunticon-embed></div>
You’d be good using Grunticon just exactly how it is. It just is a bit of a different approach than the one I’ve been talking about a lot, which uses an SVG sprite and inline <svg><use></use></svg>
.
The way I show it, you start with inline <svg>
in the document where you want the icons, and handle fallbacks from there. The possible advantages to this are:
- If inline SVG is supported, no DOM manipulation happens at all, everything is just left alone and works.
- It’s a bit easier to rip out the fallback one day if you decide you no longer need it.
- (Thanks to Scott pointing out below): Non-JS users would get SVG icons instead of fallback PNG if you chose not to Ajax for the sprite and just embed it in the document.
What’s cool about inline-<svg>
-first is that we can still use Grunticon to help us with the fallbacks!
1. Get a folder full of SVGs + Make SVG sprite
You can get them in any possible way you get get/create SVG. We’ll use IcoMoon here because it’s easy and awesome and gives us the SVG sprite right off the bat. If you want to make sprite creation part of your build, read up.
2. Use the icons as normal in your document
Simple example:
<button>
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-home">
<use xlink:href="#icon-home"></use>
</svg>
Go Home
</button>
Make sure to use the xmlns="http://www.w3.org/2000/svg"
on them, which is required to give them layout in IE 8.
3. Use the normal Grunticon build
In the Gruntfile.js:
grunticon: {
icons: {
files: [{
expand: true,
cwd: "svg/",
src: ["*.svg"],
dest: "fallbacks/"
}]
// We don't need the enhanceSVG option here
}
}
This produces all the PNG fallback stuff for you.

4. In the head of the document, run an inline SVG test
Modernizr has a great inline SVG test we’ll hijack.
var supportsSvg = function() {
var div = document.createElement('div');
div.innerHTML = '<svg/>';
return (div.firstChild && div.firstChild.namespaceURI) == 'http://www.w3.org/2000/svg';
};
if (!supportsSvg()) {
// Do Grunticon stuff
} else {
// Ajax for SVG sprite
}
5. If the test says inline SVG is supported, Ajax for the sprite
We’ve covered this before:
var ajax = new XMLHttpRequest();
ajax.open("GET", "svgdefs.svg", true);
ajax.responseType = "document";
ajax.onload = function(e) {
document.body.insertBefore(ajax.responseXML.documentElement,
document.body.childNodes[0]);
}
ajax.send();
This has nothing to do with fallbacks, this is just the normal process of fetching the icons in supported browsers. We do this so it works in IE 9/10/11 and we can browser-cache the sprite.
6. If the test says inline SVG is not supported, use Grunticon
It’s just ever-so-slightly modified in that you delete first CSS file in the grunticon()
call. That’s the one where SVG is supported, and we already have that covered.
// Inline script of grunticon.load.js here
grunticon(["", "/fallbacks/icons.data.png.css", "/fallbacks/icons.fallback.css"]);
Seems to work pretty well


If you need IE 6 and 7 too…
As is, we’re using the <svg>
element itself and setting a background on it as needed for fallbacks. IE 8 can do that, but IE 6 and 7 can’t. The SVG element will just disappear (even if you use the HTML5Shiv, weirdly enough).
If you’re in the position you need to support these ancient browsers, move the class names up to a wrapping div instead:
<div class="icon icon-credit">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-arrow-right"><use xlink:href="#icon-arrow-right"></use></svg>
</div>

Another notable IE 6-7-8 issue: you don’t get background-size
, so, generate the PNGs in the exact size you’re going to use them.
Repo
I tossed the concept up in a repo in case I screwed stuff up and y’all want to fix it.
Gotta love the Filament folks! I hope Filament Group shares some love with the Gulp community. Would be amazing to add this to my gulpfile.
Yay!
Thanks, Tim. We’ve got a plan in the works to decouple the last few grunt dependencies in there and make it gulp-able for those who prefer it. We’ll make some noise when it happens :)
Scott, you’re the best! Picturefill and Grunticon are incredibly important for my workflow. Big props.
great article and great tool !
Thanks for the writeup on your approach, Chris. I’m glad Grunticon was helpful in generating the fallbacks for the workflow you find most comfortable. I think this adds a couple steps to the typical Grunticon workflow, but if you prefer use/defs over the raw SVG markup, it’s certainly a nice way to make the tool work for you. Also, it’s a nice little bonus that a non-JS user would get SVG instead of a fallback png. Cheers :)
In the current version1, the SVG document depends on AJAX for it to be loaded into the page. Therefore, non-JS users get no icons.
From the article:
To support non-JS users, I believe the SVG element would need to be served inline with the page. I have not had the glory of using SVG elements to their potential, and barely even the lower tier uses. Therefore, you should take that statement with a grain of salt.
GitHub repo version at the time of this post ↩
Thanks Chris, Scott and the Filament Group! Great to see something new that also covers legacy browsers well enough to use in production immediately.
Filament Group rules, I’ve learned so much about doing things the
right way
from themWhat’s the advantage of this method over say using IcoMoon for SVG sprites and PNG fallbacks, with svg4everybody for old IE/Android?
This is cool http://www.grumpicon.com/
Yeah the non-js doesn’t work as the the is looking for the inline svg xlink:href=”#icon-pencil”, wouldn’t it need to be something like xlink:href=”svgdefs.svg#icon-pencil”. But this would then underpin the caching effect.