Why and how I ditched icon fonts in favor of inline SVGOctober 31st, 2014
Webfonts are the new hotness, and icon fonts even more so. There’s plenty to choose from, and Google just released an icon font that’s based on the new Android L. Icon nirvana reached?
Not really. Icon fonts have a few nasty problems that icon font makers rarely make you aware of. Here’s a few of these problems:
If you serve icons from a service, that services might randomly go down. I’ve seen this over and over again with big and small websites.
You can’t easily edit icons, and it’s hard to see what’s been updated in source code control. Webfont files are for the most part binary and changing one icon normally means the whole resulting font file is different.
There’s blurry rendering on certain browsers. Some CSS properties have to be abused (like
-webkit-font-smoothing: antialiased;) to make the icons look good. This doesn’t work in some browsers and in some browser versions.
Most importantly, when icons are in the same CSS block, or when centered in an odd-width container, you get off by half-a-pixel blurryness, which can’t be corrected. This happens on all browsers, even on the latest and greatest Firefox, Chrome and Safari (even though Safari is doing better than IE, Firefox and Chrome, I’ve seen it happen on Safari as well).
Here’s some screenshots from GitHub on IE 10, showing this issue (it also happens with other browsers, like Chrome):
In Freckle Time Tracking we had a clever setup with SVG source files (on a precise 16×16 grid) and using
fontcustom to compile fonts and doing some post-processing of the generated CSS with
sed (most to remove unwanted font variants, as you only need
woff in recent-ish browsers).
We also required to add some special headers when serving these font files so that our CDN (Amazon CloudFront) would correctly serve them.
All of this worked, but… blurryness alarm!
Back to square one
Let’s take a step back and ask—what do you need from an icon? Why do icon fonts appear to be a good solution? And how can the problems be fixed?
- Icons need to be rendered pristinely and in focus.
- They should ideally be rendered the same or nearly the same on all browsers you support.
- You should be able to change the color and ideally other (CSS) properties.
- The same icon should look great on normal and retina screens; ideally you can substitute a different version for retina if you so fancy.
- It would be great if the files are text, so they work great with source code management. (Did you know that GitHub does graphical SVG diffs?)
Inline SVG to the rescue…
Here’s our current workflow:
- We’ve a bunch of SVG files in a folder, which are our icons. All of them are on a 16×16 pixel grid.
#!/bin/sh # This requires "imagemin", install via: # npm install --global imagemin echo "Cleaning up..." rm -rf build mkdir build echo "Optimizing SVG..." imagemin *.svg ../public/images/icons ruby ./generate_helper.rb
- For the optimization, we use imagemin, which will remove unnecessary stuff from the source SVG files (these are all saved in Adobe Illustrator, which likes to be on the verbose side when it comes to saving SVG).
- There’s a Ruby script that reads the optimized SVG files one by one and generates a Rails helper file with
icon_xxxxxmethods. These methods can be called from any view to insert the desired icon as inline SVG:
Last but not least, the optimized files are copied into
/public/imagesso you can use
them for special cases when you don’t want inline SVG but a normal image tag or a background image.
To set the color of an icon in CSS, just add a
fill: #abcdef;CSS property.
Boom—problem solved. This works great on all browsers, and you don’t get any of the rendering issues that you have with icon fonts.
Actually there’s several unexpected advantages:
- When you copy+paste text, the SVG is ignored so you don’t get weird extra characters in the pasted text.
- There’s no weird “flash of unstyled text”, neither is there empty spaces that are only rendered when an icon font was fully loaded.
The only downside is perhaps that your HTML will be slightly larger than it would be with an icon font, which might result in slighter longer loading and rendering times. This is offset by not having to load an icon font in the first place, however, and in my tests has not been a problem at all. A possible way to reduce the HTML size is to set
Enjoy the SVG goodness!Tweet