Bulletproof SVGs with Grunticon

What is Grunticon?

Grunticon is my favorite way to serve SVGs when a site needs to support older browsers. According to the official website, Grunticon is:

[…] a Grunt.js task that makes it easy to manage icons and background images for all devices, preferring HD (retina) SVG icons but also provides fallback support for standard definition browsers, and old browsers alike. From a CSS perspective, it’s easy to use, as it generates a class referencing each icon, and doesn’t use CSS sprites.

We’ve used Grunticon at Sparkbox for quite some time in lieu of using font icons (which come with their own issues as CloudFour has documented so well). Grunticon lets us use SVGs for the browsers that support them, and it automates a fallback to PNGs in browsers that don’t. All that’s required is a bit of Javascript in the <head> of the document to determine the capabilities of the browser.

A big perk of Grunticon is that it delivers assets in a performant way. If the browser supports Base64 encoded images, it will deliver a single stylesheet containing all the icons as individual background images in unique classes. Of course, if the browser doesn’t support this approach, Grunticon will fall back to serving a stylesheet with individual image assets.

Grunticon works really well without much configuration, but there are a couple pieces of configuration that really make it sing and scale much better when working with multiple developers. My two favorites are colors and custom selectors.

Colors

One of the easiest wins is to use Grunticon’s support for color. Grunticon does this by scanning each icon filename for the pattern .colors. A hex value after .colors is used to generate copies of the icon in the color specified by the hex value; for example, hamburger.colors-000.svg would generate the hamburger in #000 (black) with the class name icon-hamburger-0.

While this is useful, it can be confusing to navigate a filename with multiple hex values in it. Grunticon’s naming convention of applying an incrementing number to the file (that -0) doesn’t help either. Thankfully, you can define a color object in Grunticon’s options that contains hex values as values tied to a name key, like so:

const options = {
colors: {
blue: "#0000FF"
}
}

Once you have a color in place, you can use that color key in the filename of an SVG to generate a version of that icon in that color. Any words after .colors are compared to the colors object to find the correct hex value; for example, hamburger.colors-blue.svg would generate the hamburger icon in blue. The generated icon and class name is icon-hamburger-blue, much better than icon-hamburger-0. This makes color changes trivial—no need to open up a graphics editor to change an icon. Just change the filename and the color object.

Custom Selectors

So colors are pretty nifty, but it wasn’t until I understood this next aspect of Grunticon that it really took off for me. Often, an icon will need to be dynamic (e.g., change colors when hovered or swap an icon out completely when an input is :checked). Since Grunticon delivers a separate stylesheet, there didn’t seem to be a clean way to modify the generated CSS. In the past, I’ve applied the icon states (a hovered state and a normal state) to spans and then wrapped them in a div. I would then hide or show the appropriate icon based on the parent icon. This isn’t a great solution. It works, but it’s not ideal.

Thankfully, Grunticon has a feature, custom selectors, to address this issue. Custom selectors let you define an additional string of CSS for an icon. The custom selectors object takes a key, which is the name of the icon to which you want to add additional CSS. The values of that key are the additional CSS selectors to append to the generated Grunticon stylesheet.

customselectors: {
'arrow-black': ['.icon-arrow-white:hover']
}

The example above is going to show the white arrow icon when the black arrow icon is hovered. Remember, this (ideally) is all in a single stylesheet, so it will behave like a sprite—there won’t be a loading flash.

Better Icons. Better Workflow. Grunticon.

Grunticon is an awesome tool that enables a really solid icon workflow. At the end of the day, though, it’s just a tool. If a project doesn’t need to support browsers that don’t support SVGs, then just use plain ‘ole SVGs. Context is everything. However, if you are dealing with browsers that don’t handle SVGs well, I would heartily recommend giving Grunticon a look.