With mobile devices accounting for over 10% of all Web traffic and hardware manufacturers producing higher pixel density screens, it’s clear that the days of one-size-fits-all icon sprite images are coming to an end. Icon fonts (aka symbol fonts) have grown in popularity as one such replacement for traditional sprite and icon sets because they produce high quality vector shapes without the hefty download and are compatible with most legacy browsers.
While there are many great icon font libraries that offer an endless variety of icons, occasionally a project calls for something more custom. That was the case at Sprout, where we had over 100 custom icons in sprite files and needed a more manageable solution that was seamless and maintained our branding. In this post, I will walk through the steps of creating a custom icon font.
The tools I’ll be using are Adobe Illustrator to design the icons, Fontlab’s TypeTool 3 to build the typeface and Font Squirrel’s @Font-Face generator to generate the web font. While there are a variety of other font authoring tools that can do the job, I chose TypeTool because it is relatively inexpensive, bare bones compared to other applications and most importantly plays nice with copy and paste from Illustrator. Other options like the robust FontLab Studio, Glyphs App and FontForge are also worth evaluating.
Before we start
Open your (vector) Icons or Sprite file and determine which icons you want to add to the font. You’ll need to make sure that the icons you are going to use are or can be deduced to basic, one-color shapes with no stroke or layer effects such as glows, shadows or gradients. When you implement the font you’ll be able to customize colors and effects via CSS but the font glyphs must be unstyled.
Above is an sample Sprite image that has a variety of similar icons that could be re-styled via CSS to match the original versions.
One of the most common pitfalls with creating an icon font is semantics. It’s easy to open your font editor, look at the alphabet and plan your alpha numeric key mappings, such as “P” for a push pin or “E” for envelope, but there are two major problems with this. First, there is a good chance you’re eventually going to have more than two icons that start with “P” which can lead to a cryptic naming structure with loose or no semantic meaning. Second, if the web font fails to load, your icon font will fall back to the site’s default font, exposing a bunch of seemingly random characters to your visitors. Fortunately, the solution is as simple as π.
By mapping your font to Unicode characters, you add semantic meaning through a global convention that, in many cases has a native default font fallback. The Unicode standard also contains thousands of characters, which is great for selection purposes but sometimes creates a daunting game of choosing the “right” match. Luckily, there are some great resources to help, such as: Learning jQuery’s Unicode Chart Index, Unicode.org’s Character Name Chart, Wikipedia’s Unicode List, Unicode.org’s PDFs and the very handy Shapecatcher utility (a personal favorite) which allows you to draw symbols on screen and searches a database for matches. Even with the thousands of Unicode options, there might be icons that can’t be matched; in these rare cases I generally make the exception of using traditional characters (“@” for a Twitter bird, for example.)
Building the Grid
First, we’ll need to setup a grid for our glyphs to assure they are sized consistently. Open TypeTool and create a new font (File > New). Click the Font Info button to bring up the settings menu for the new font. Click on the Metrics and Dimensions node
Enter 1000 for the value of Font UPM size. At this point if you’ve never made a font before you’re probably wondering: “What the hell is a UPM?” and “Why 1000 instead of the default 2048 or any other number?” A UPM is simply the size of the font measured in Units Per eM, as for what size to use, I suggest researching this more on your own before you decide, but there is also a very lengthy discussion at Typophile on the subject. In the end, I chose 1000 UPM for this demo because it divides evenly to many numbers and is easy to manage from the grid template perspective. The GitHub front-end team also offers some good insight starting on slide #68 of this presentation (they went with 2048).
The objective is to make the Illustrator grid identical to the grid in TypeTool so there can be a seamless copy and paste between the applications but before that can be done Illustrator must first be configured. Still in TypeTool, go to your font’s settings and click on the Key Dimensions node, then open Illustrator.
Create a new file, for the dimensions choose 1000pt / 1000pt (note: this number should match your UPM size so you’ll need to change if you’re not using 1000 UPM). Now we need to make sure the Illustrator preferences are set properly:
- Enable Snap to Grid
- Show Rulers
- Show Grid
- In Preferences > Guide / Grid: Set “Gridline Every” and Subdivisions to 10pt and 10 respectively
- In Preferences > Units set all units to “Points”
- In Preferences > File Handling & Clipboard uncheck “PDF”, Check “AICB” and choose the “Preserve Paths” radio button
To create the grid add four vertical guides at the heights corresponding to the Key Dimensions values in TypeTool for: Ascender, Caps Height, X-Height and Baseline (which is 0pt).
As an Illustrator novice, this part took some time to get right so I’ve uploaded the template used for this demo here.
Making the Font
At this point we have set our default settings in TypeTool and now have a matching grid in Illustrator and are ready to start making the actual font. If you are unfamiliar with type terminology like Ascender, Descender and X-Height, take a look at this diagram:
More detailed info on these terms can be found here.
In the context of an Icon Font, these terms have a slightly different meaning since there probably aren’t going to be capital letters and descenders so for general use the only two that you will need to care about are Ascender and Baseline.
Next, locate your icon source files and copy and paste your first icon into the grid template. At this point your icon is probably much smaller than the grid and will need to be re-sized.
Position your icon in the bottom left corner, right above the Baseline and resize it so that the top most edge touches the Ascender. This will assure that all of our Symbols are the size of capital letters, producing a base size that will play nice with most common fonts once in your CSS.
Back in TypeTool, double click on a glyph (any non-used glyph will work, we’ll rename it in the next step) and paste your symbol into the resulting Glyph Editor window.
Since the Illustrator grid was mapped to the specifications of the font, the pasted icon should line up perfectly with TypeTool’s top, left and bottom grid.
Close the Glyph Editor window and then right click on the square of the icon you just pasted and choose Rename.
Here you can enter text (no spaces if you want full OT browser support) in the NAME field and paste the Unicode value that you mapped earlier in the Unicode field. Only the Hexadecimal code version will work; if you don’t know it, this tool that you should definitely bookmark right now easily converts Unicode characters for you.
Repeat these steps for each subsequent icon. Once renamed, you’ll notice that the glyph is now re-classified with its new name and unicode value. A nice way to keep track of this is to use TypeTool’s Codepage / Name button to toggle between glyph names and Unicode values.
When glyph naming and mapping is complete, it’s time to export. In TypeTool, click File > Generate Font and choose OpenType PS as the format. In this tutorial I am not going to cover OpenType Ligature support, as seen in fonts like Symbolset. Nonetheless, your font will be future-friendly if you decide to add OpenType features. If you are interested in reading a little more about Ligature options, Brian Suda’s ALA article has some great insight.
Generate the @Font-Face
We now have a beautiful designed, fully-customized font that is ready to bestow its glory on the web. In order to do this we’ll first need to make it
@font-face friendly. My favorite way to do this is through Font Squirrel’s
Because we’re using fancy Unicode mapping, we’re going to have to use Expert mode and change the following settings for Format:
- EOT Compressed
- Subsetting:Custom Subsetting…
- Character Encoding: Roman
- Unicode Ranges: You’ll need to enter *EACH* Unicode symbol used in your font, comma separated. This part is tedious so make sure to preserve the list for future use.
If you plan to use a CDN / host that does not have CORS support enabled, you will likely need to choose Base64 Encode in the CSS option area or else your font will not load in Firefox (more on that: here and here). That said, most CDNs do allow CORS and even long holdout Amazon S3 recently added support.
To finish up, choose a prefix for your font in Advanced Options and make sure to choose “Remember my settings” in Shortcuts, download the zip file and upload the fonts to your server.
Adding the font to your site
ZIP file from Font Squirrel contains a
CSS file, you will need to do a couple more steps for full browser support. If you haven’t read Paul Irish’s Bulletproof @font-face article, please do that now. Don’t worry, I’ll wait.
Here is the final product, compatible with IE6+ and all modern browsers:
If you’re going the Base64 route, reference the
CSS file from the Font Squirrel zip and paste the Base64 data in to the
WOFF url section of your
Using the font
To use the Font Icons, define a base class containing the defaults for your font icons, such as:
then add the
.yourSymbolFont class to an element and add desired Unicode entity to your your element:
Wait, you forgot the Hexadecimal Numeric code for your icon didn’t you? Here’s a link to that converter again. At Sprout, we found the easiest way to reference the Unicode value pairings was to make a table that maps the icons to their Unicode values.
At this point we’ve covered the basic methods for creating and implementing a custom icon font. There are many more related topics and best practices that, for the sake of brevity, I was not able to cover. I encourage you to explore and share new ways to improve this process on your own. I welcome your questions and feedback in the comments and on Twitter @bahnburner.