SVG Spriting with Grunt
by Steven Bone on 08/21/14
Easy SVG sprites with grunt
The past few months we've been designing and building our own icon system, and implementing it with SVG.
The two most popular approaches both use inline SVG, either in your HTML markup or via CSS classes. We chose to use CSS classes, but sometimes inline SVG HTML in a pinch (more on that later).
Getting Started
All our design assets are in Adobe Illustrator. Each icon is its own Artboard allowing you to easily save each one as its own SVG file. VHX is built on Rails, and we currently rely on the Asset Pipeline and Compass. Compass is great for spriting with PNGs, but it doesn't currently support SVG. (There's a long standing issue in Compass' Github project.)
We'd been wanting to use the JS-based task runner, Grunt, and this was a perfect chance to get started. Chris Coyier's post on CSS-Tricks is a handy reference for this.
Why Grunt?
Grunt is written in Javascript.
Grunt is great for frontend developers. We use Grunt as an asset builder - JS better empowers us to iterate fast, experiment, and refine this process.
Grunt is fast.
Because Grunt handles asset-related tasks exclusively, it's been really speedy. Very important while you're tinkering.
Grunt is portable.
Compared to refining a workflow within the Asset Pipeline, migrating Grunt setups between different apps and frameworks is just a matter of changing file paths.
Implementation
After creating a folder called SVG
in our app that stores all our our icons from Illustrator, we use Grunt tasks for the heavy lifting:
- file-regex-rename to normalize SVG names
- svgmin cleans and minifies the SVGs
- grunticon to build the line CSS-inline sprite
- copy to create a file of silent classes for
@extend
usage throughout your app (optional) - svgstore for creating an HTML-inline sprite (optional)
Why are steps 4 and 5 optional?
copy
is only needed if you want to use SASS @extend
s for icons within your CSS, outside
of the classnames generated by grunticon. We have it configured to create a duplicate of grunticon's SVG stylesheet,
replacing each class' leading .
with %
. Otherwise, using @import
at the top of every SASS file in your app will
create hundreds of duplicate lines of CSS.
svgstore
is specifically for creating a HTML-inline SVG sprite. Now why would you want one of those?
CSS versus HTML-inlining of SVG
At it's core, the main differentiators of these two approaches are:
- Inline HTML allows you to leverage common CSS or JS behaviors to change the color of the icon (e.g., on mouse
:hover
, make the icon a different color). - If you design icons with more than one color in it, you will have to use CSS-inline.
Caveats
- CSS-inline: Your SVG is a background-image, and you can't modify it with CSS or JS. The best we've done
is use
@extend
to use a different colored version (generated by grunticon). You can't add CSS transitions to this. - HTML-inline: You cannot target individual paths of an SVG, making multi-colored icons a bit of a bust.
Moving Ahead
One of our icons in multiple colors and sizes, all generated from a single SVG file with Grunt:
An icon using HTML inline SVG, with a CSS transition on :hover
:
Once you have this setup for your app, managing your icons will be a breeze. We're liking this Grunt-based workflow a lot, and are planning to migrate away from the Asset Pipeline entirely for it. Follow-up post once that happens!