100% Awesome SVG Icons

So, you may have read about how SVG Icons are better than font icons, but still aren’t ready for prime-time yet. Well, I’m here to tell you that they finally are.

The recipe for my little icon stack is pretty simple, but you’ll need a few things:

If you’re using gulp, feel free to grab the gulp-imagemin and gulp-raster plugins, since they’ll make your life a lot easier. Imagemin basically just compresses your images (including SVGs!), while Raster uses PhantomJS and some neat trickery to generate PNG fallbacks.

Here’s what my gulpfile looks like (yeah, I’m using coffeescript):

# load gulp and utils
gulp         = require 'gulp'
changed      = require 'gulp-changed'
rename       = require 'gulp-rename'

# image / icon tasks
imagemin     = require 'gulp-imagemin'
raster       = require 'gulp-raster'

# build icons + fallbacks
gulp.task 'icons', ->
    gulp.src 'assets/icons/*'
        .pipe changed 'dist/icons'
        .pipe imagemin() # compress icons
        .pipe gulp.dest 'dist/icons' # optimized svg icons go here
        .pipe raster() # this takes a few seconds to run, hence using changed() to only run on new/changed files
        .pipe rename { extname: '.png' }
        .pipe gulp.dest 'dist/icons/png' # dump the pngs in here

As you can see, the task optimizes our svg icons (removing a bunch of cruft), then generates PNG fallbacks automatically. Now, we can use the icons in our webpage like this:

<img src="dist/phone-icon.svg" />

Super simple. If we include SVGInjector in our scripts, it will run on page load and replace the <img> element with an <svg>, allowing us to apply a lot more styling than we would be able to using grunticon or an icon font.

If you’re using these icons in something like Angular, where they won’t always exist in the DOM on page load, here’s a neat little directive you can use to initialize the icons. Make sure you add the iconic class to your <img> tag!

// init svg-injector
app.directive('iconic', function() {
    return {
        restrict: 'C',
        link: function(scope, elem, attrs) {
            window.SVGInjector(elem, {
                evalScripts: 'once',
                pngFallback: 'dist/icons/png'
            });
        }
    }
});

That’s all there is to it! Enjoy using CSS transforms, line animation, smart icons, and more. Enjoy never having to worry about fallbacks ever again.

UPDATE - It was mentioned in the CSS Tricks article, but you should really be using accessible SVGs. I’m not sure if SVGGO (the tool that gulp-imagemin uses internally to optimize SVGs) overwrites some or all of those attributes, so definitely do some experimenting. The fallbacks and SVGInjector work perfectly even with un-optimized SVGs.