Icon Fonts Are Ruining Your Markup

Icon fonts are great. They’re more scalable than PNGs, they’re re-colorable in CSS, and it’s easier than ever to create them. But most of us are using them wrong, and it’s ruining your markup. Recognize this?

<span class="icon icon-calendar"></span>

This is fast becoming the de-facto standard syntax for inserting icons in your webdesigns. No need to fiddle with weird glyphs. No CSS needed to insert icons, even.

No CSS.

Hold up. The promise of CSS was that we could separate presentation from markup. We could create standardized, semantic and sensible markup, that could then be completely re-skinned solely by replacing a stylesheet. That was the whole point of the CSS Zen Garden. By using nonsense spans with verbose classes, that’s out the window, all in the name of convenience. I too have been bitten by the icon-font bug. I’m into them. I think it’s so great that I can re-color icons with a line of CSS. I like how they zoom, and how they have broader support than SVGs.

But they’re not SVGs. They’re not images. We shouldn’t pretend they were, or that they could ever be as accessible as images are.

Theoretically an icon from a font could be inserted in a semi-accessible way by outputting the actual glyph in the code to ensure copy/paste-ability. You’d also have to make sure to only use an icon that already existed in the unicode-table so screen-readers could make sense of them, thus severely limiting your options as a designer. Need a hamburger menu icon? Sorry, doesn’t exist in the unicode table. Pretty much all the benefits of using an icon font would be out the window at this point.

Rewind for a bit. Take a deep breath and think. Why are you using an icon font in the first place? Easy HiDPI and CSS colorability? Easy to show at multiple sizes? Fair enough.

Now pretend icon fonts didn’t exist, what would you do instead? Use a PNG or GIF as a CSS background, right? You’d treat the graphics as presentational elements. Visual aids. You’d keep it separate from your markup. You’d be able to reskin your whole site with a single stylesheet. You’d keep the markup as simple and semantic as that of the CSS Zen Garden. Hopefully you’d be a good person and worry about accessability where it mattered most: in the structure of your markup.

You can still use icon-fonts and have sensible markup while keeping the presentation separate. But doing so means you can’t rely on those bundled CSS helper classes. You have to do it manually; put in the work. Don’t treat icon-fonts like images. Pretend they’re sprites and keep them in your stylesheet. You’ll thank me.

Do’s and Don’ts of Icon Fonts

Having worked on icon fonts a lot in this past year, I’ve learned many things about them I did not know before. In some ways they’re more useful than I thought (yes, icons can actually be pixel-perfect), in other ways less so (pretend Firefox doesn’t exist until it reaches version 25). Since icon fonts are booming these days, I thought it useful to share some do’s and don’ts that I’ve picked up over the course.

An icon font is a font that contains symbols and graphics instead of letters and numbers. Remember Wingdings? These symbol fonts are incredibly useful because they allow webdesigners to do things they can’t do with PNG or GIF graphics:

  • it’s HiDPI out of the box
  • they scale well (more on that later)
  • it’s easy to pick colors using only CSS

They’re so pleasant to work with that it’s easy to get carried away by the obvious benefits over PNGs. Unfortunately there are a number of limitations to be mindful of. Most of these can be mitigated by using icon fonts properly.

Scalability at small sizes

Just because icon fonts are technically vector graphics, doesn’t mean they all look great at any size shown. Especially at small sizes, icon fonts start falling apart. This is why good icon fonts are designed according to a pixel grid.

A pixel grid is a minimum resolution at which embedded icons show up crisp. Typically such a resolution is 16x16px (which translates to font-size: 16px) or 20x20px (which translates to font-size: 20px;). If you use the icons outside of their intended grid, the icons will get blurred and details become fuzzy. If you show an icon intended for 16px at 17px, it will look positively atrocious.

We’re used to this from the Nintendo 8-bit days: there’s only so much resolution to work with. Unless you place your pixels precisely, your graphics won’t be clear. Being vector graphics doesn’t change this one bit: at 16x16px it doesn’t matter how scalable your icon is.

Remember, even if you’re used to being able to use many different font sizes for actual fonts, icons are a different thing. Not only are our brains trained to recognize letters, but fonts themselves are designed to render letters for maximum legibility. Fonts rely on the fact that we read horisontally, and hints letters so that subpixel antialiasing ensures horisontal crispness at many arbitrary sizes. This subpixel antialasing does not translate to icons. Icon fonts won’t ever look as good as normal fonts do at arbitrary sizes.

Let there be no doubt in anyones mind: using icon fonts for web graphics is a hack!

It is a glorious, wonderful hack. But it is a hack. We have to be mindful how we use it.

Crossdomain fonts

Firefox blocks a stylesheet from example.com from loading a font hosted on cdn.example.com. It is an intended font piracy/hotlinking measure. The workaround is simple, but easy to forget when you’re pounding your head against the desk unsure why icons show up fine in Chrome but not Firefox.

The easiest workaround is to base64 encode the font file itself and embed it in the stylesheet. By being embedded directly in the stylesheet, no domain hops are necessary, and Firefox loads the font. Most icon font bundles (such as Genericons) come with base64 in tow, but if you’re making your own icon fonts, I recommend using FontSquirrel’s Webfont Generator which will optionally base64 encode for you.

Inserting icons

Because icon fonts are hacks, most icon font packs been through a rather lengthy process to make them as easy to use in webdesigns as possible. Ideally it’s a matter of referencing a stylesheet and copy/pasting a snippet of code.

But don’t get carried away. Behind the scenes numerous decisions have been made in order to make your icon fonts that simple to use. Some of those decisions have consequences outside of just the icons.

This is going to vary from icon font to icon font, but let me go through how the Genericons copy/paste tool works.

Glyphs

Right on the Genericons homepage, the third copy option next to the big icon preview is “Copy Glyph”. This is intended only for use in your Photoshop mockups. You download the icon font and install it on your system. Now in Photoshop you can paste the glyph in a textarea, set it to the Genericons font and the icon will show up.

It is not intended to paste in your actual HTML. Remember, icon fonts is a hack, and a screen-reader wouldn’t know what to do with a weird unicode symbol. Incidentally that means we can only rely on using CSS’s :before selector to insert the glyphs. That means using icon fonts in an accessible manner can never work on IE7.

Copy HTML

For casual users who want to insert Genericons as they would smileys, the “Copy HTML” feature is provided. In effort to make it as easy as possible to get the ball rolling and an icon showing, some helper CSS is provided with Genericons where every icon is mapped to a preset of named classes, for example:

<div class="genericon genericon-calendar"></div>

That’s a lot of CSS classes inside a redundant empty div, don’t you think? Yep. It’s not great code. But it’s really easy to insert, so the casual user doesn’t have to worry about the CSS. It’s perfect if you mean to insert a star icon in the middle of that article you’re writing in your CMS of choice.

Copy CSS

This is the option non-casual webdesigners should use. While also the least easy way to insert an icon (since you’ll effectively be re-writing some of the bundled helper CSS), it’s not actually as hard as I may be presenting it here. You should be using this method because:

  • it’s the most accessible — screen readers don’t even attempt to read the icons aloud because they’re inserted using only CSS
  • it’s the cleanest — there are no extra CSS classes and no redundant markup
  • you have the most control: since you write all the CSS, you don’t have to unstyle some of the bundled Genericons helper CSS you don’t need

The process is to essentially manually attach the icons to the :before selector of the class needed:

.my-element:before {
	content: '\f408';
	display: inline-block;
	-webkit-font-smoothing: antialiased;
	font: normal 16px/1 'Genericons';
	vertical-align: top;
}

The content: '\f408'; part is what you get from the “Copy CSS” tool. You can structure your own CSS as you wish to minimize code duplication.

In summary

Using icon fonts is a wonderful hack that brings many convenient features, but unless you’re using them right, you’ll end up with fuzzy graphics. Knowing is half the battle, and here are the rules:

Rule #1: When showing icons small, do not stray from the font pixel-grid (unless you have a good reason). If the grid is 16×16, show the font at font-size: 16px exactly.

Rule #2: Don’t rely too heavily on the helper CSS, that is intended only for casual use.

Now go use some icon fonts.

Genericons

An Automattic 20% project of mine just graduated. Genericons is an icon font with emphasis on blogging. It’s GPL, so you can bundle it with WordPress themes. What makes Genericons special is that, like its inspiration: Githubs Octicons, the font was designed with a precise pixel grid in mind. That means if the icons are shown at appropriate font sizes (in this case, 16px, 32px, and similar multiples), the icons will render perfectly crisply. Thanks to Sheri and Takashi for contributions.

Font Smoothing

If you’re really into icon fonts, which I have recently become, you may have noticed a tiny storm brewing in the suburbs of the internet. It’s about CSS-specified font smoothing. Quite a nichy topic, one you can live a perfectly good life without ever knowing all about. You may in fact sleep better by not reading on.

Still here? Alright, here’s the deal. WebKit — born of Safari, engine of Chrome — allows webdevelopers to specify how the edges of fonts are smoothed. The modern default font smoothing method is called subpixel antialiasing. It smoothes font edges using quite impressive means, and in nearly all cases it drastically improves the rendering of letters. If you look at the text in a magnifying glass, though, you’ll notice a nearly imperceptible blue haze on the left side of each letter, and a red haze on the right side. WebKit provides a means for webdevelopers to pick which type of font smoothing is applied: subpixel-antialiasing, antialiasing, or none. Handy. Right?

The controversy is the fact that a number of people — smart people — feel that this CSS property is damaging to the readability of text on the web. There are very long articles on the topic. In fact quite recently a Google employee removed the CSS property from Chrome, citing the notion that the browser should render text according to the operating system. There’s just one problem: icon fonts.

Icon fonts are custom-made webfonts that contain no letters, only icons. The purpose is to have fast access to a bunch of icons in a very lightweight and easy way in your webdesigns. Other benefits include the fact that the icons are infinitely scalable because they’re vector graphics, and you can easily apply any color, drop-shadow or even a gradient to each icon using plain CSS. Sounds brilliant, doesn’t it?

The only downside is that an icon font is still technically a font, so the computer thinks each icon is actually a letter, and by default will try to subpixel antialias it. While subpixel antialiasing does wonders to letters, it’ll fuzzy up your icons and make them look blurry. Which is why the -webkit-font-smoothing property was so welcome. Here’s an icon font without and with subpixel antialiasing:

As you can imagine, I’m strongly in favor of not only keeping the font-smoothing property, but in fact expanding it beyond WebKit to both Firefox and Internet Explorer. Icon fonts won’t be a truly viable webdesign technique until every icon looks great on all the platforms.

“But SVG is the future of vector graphics on the web, surely you know that!” — Yes I do. But pragmatically speaking, that future is not here yet. SVG support is still lacklustre, especially when used as CSS backgrounds. More importantly, you can’t easily change the color of an SVG icon using CSS only, or apply a drop-shadow. Yes, drop-shadows are on the road map for SVG, but the way it’ll happen is not pretty. Icon fonts, on the other hand, provide a real-world solution today, which is both flexible and infinitely scalable. So next time you see someone bad-mouthing -webkit-font-smoothing, pat them on the head and mention icon fonts. The more you know.