Customizing Fork Awesome

Font Awesome became, over the last six years, the de-facto standard free icon font for web applications. However, since 2016, it declined, closing itself to new icon submissions, and near the end of 2017 released a new, commercial version 5, incompatible with free software. The free tier of the font also removed some useful icons, and looks rather mediocre. This lead to a fork of the last free version, 4.7, fittingly called Fork Awesome. This article looks at the guts of such icon font, and explores a way to customize it (specifically, how to remove unused icons).

How Is an Icon Font Made

The alchemy behind traditional font design, getting the proportions just right, aligning characters etc., is well beyond me. However, icon fonts are relatively simple and it's not hard to grasp the basic concepts.

At the beginning lies a set of SVG files, carefully aligned to look right when placed on a line together with some text. These files are fed to a tool, such as Font Forge, which combines them and outputs a font file, such as TTF or OTF. Easy, right? We're done? Not so quick.

Code Points

One thing to consider when designing a font is the character mapping—which code point maps to which symbol. Ancient icon fonts, such as webdings, mapped characters from the extended ASCII table to symbols, so you could simply type e.g. "a" and get check mark. An important downsite of this approach is that if you don't have the font installed, you get a letter soup that makes no sense, and it may not be obvious they were supposed to be icons. It is also a complication for assistive technologies, which will try to read the normal letters.

A more modern approach is to use code points from the Unicode Private Use Area (PUA). Those characters have no designated meaning, and thus are a perfect fit for icon fonts. Naturally, we should accompany our icons with tooltips and aria labels when used on the web, unless they are accompanied by a regular text label. A button with only an icon in it is not great for screen readers or people who fail to load the font.

Into the Browser

So now we have the font file, what's next? We need to get it into the web page. Luckily, this is possible with CSS. The syntax is somewhat arcane, but there are plenty examples to go by. I've built a custom version of Fork Awesome as a demo for this post, including just three icons, two of which are shown in the intro paragraph. The CSS block used to load it into the page goes like this:

@font-face {
  font-family: 'fa-6zjwb';
  src: url('./fa-6zjwb.eot?v=1.1.0');
  src: url('./fa-6zjwb.eot?#iefix&v=1.1.0') format('embedded-opentype'),
       url('./fa-6zjwb.woff2?v=1.1.0') format('woff2'),
       url('./fa-6zjwb.ttf?v=1.1.0') format('truetype'),
       url('./fa-6zjwb.svg?v=1.1.0#fa-6zjwb') format('svg');
  font-weight: normal;
  font-style: normal;
}

From this point, you can use the font-family directive with fa-6zjwb as the font name anywhere in the page, and it should load the font.

One more problem needs to be solved, though—how to get the right characters into the page. We could use the HTML entity, , , in an element using the custom font. That works: . You're welcome to inspect this smiley with your dev tools. However, we can do better with CSS3 pseudo-elements.

The simplest CSS using pseudo-elements to put font icons into the page could be something like this:

.smiley::before {
  display: inline-block;
  font-family: "fa-6zjwb";
  content: "\f102";
}

Fork Awesome uses this this trick, accompanied by a bunch of helper classes, to e.g. make the icons spin . The content directive defines the text inside our pseudo-element, so to get the right characters into the page, all it takes is one such style per symbol. For the demo font, that is:

.xx-font-awesome::before { content: "\f100"; }
.xx-fork-awesome::before { content: "\f101"; }
.xx-smile-o::before { content: "\f102"; }

The Dark Side of Icon Fonts

Icon fonts are a nifty way to get consistent scalable icons with little effort, assuming someone already put in the hard work. What are the drawbacks? Basically what you might expect: the fonts are additional files that need to be loaded by the browser to render the web page. The SVG version of Fork Awesome has whooping 450 kilobytes! It's not so bad for the other formats, but it's still an extra burden. In theory this could be fixed by HTTP/2, but we're not quite there yet—and it's little consolation when someone simply has dial-up connection speeds; that's still a thing, unfortunately.

A good approach to reduce the fonts' impact on the page load speed is to remove icons we don't use. There are over six hundred icons in Font Awesome 4.7, and over three thousand in the commercial version 5. Fork Awesome still has under one thousand, but that's still a lot, especially if you won't ever use most of them. Let's dive into its code--thankfully it's open

Reduction Diet for Fork Awesome

The Fork Awesome repository (at the time of writing) is somewhat messy, a legacy of Font Awesome. Getting it to even build took me some trial and error. Anyway, it can be done, how else would they add new icons to 4.7, right? After some inspection you will find that there is a makefile in the src/icons folder, which packs SVG files in the src/icons/svg folder and produces font files. The tool called from here is Font Custom, a ruby gem using Font Forge. The project seems somewhat stale, maybe as a result of the Font Awesome lock-down. I'm not sure, but I made a local mirror of it anyway, just to be sure.

Font Custom generates our icon fonts and a preview page (like the one I linked above) based on a config file fontcustom.yml and a list of icons icons.yml. It also generates a manifest file .fontcustom-manifest.json, which we can to delete to force a rebuild of the font.

It would appear that by simply removing icons from the icons.yml file, we can limit the content of the generated font files. Not so. Font Custom apparently assigns automatic code points to SVG icons that aren't described in here. After deleting unused icons from the svg folder, it finally obeys and produces our custom version of the font.

A problem with this hack is that the generated CSS file is not actually used by the rest of the Fork Awesome "toolchain". The CSS, SCSS and LESS directories have hardcoded lists of icons that we would have to adjust as well, if we wanted to limit the icons in the final CSS file. But there is no need, if we can do with the simpler CSS file generated by Font Custom.

Getting Automated

This whole endeavour is one big tangent stemming from me needing an icon for one of my projects, and thinking how the font could be slimmed down. There is Fontello, but it doesn't include Fork Awesome (also doesn't load over HTTPS—in 2018. WTF??). I spend a couple hours messing with files in the Fork Awesome repository, and finally found the above described method of customizing the font. A bit after my usual bedtime, a working customizer saw the light of day (or, rather, moonlight).

You can try the customizer here: git.ondrovo.com/MightyPork/fork-awesome-customizer

Read the README (duh). I might try to incorporate this into the upstream project later, but for now this is your best bet.

Here's what it should look like when you're building a custom font with it:

Found something wrong or have a question?
You can use e-mail or find me on Mastodon.