Font icons like a boss with Sass & Font Custom

⚠️ This article is outdated: First I moved on to a custom Gulp workflow, then for a while I used SVG symbols and external references with a polyfill. Now I use inline SVG React components, and occasionally plain old .svg files in img tags.

Here we take “Fun with Sass & font icons” to the next level by automating the tedious stuff, including the actual font generation.

Manage all your project’s font icons in one folder as nicely named SVG files. Add icons to this folder to have your fonts magically rebuilt and your Sass automatically set up for you to start using the icons via their nice names; without touching your markup or dealing with non-semantic class names.

What are the perks?

  • Manage your icon font entirely offline. Save yourself trouble manually configuring, downloading and integrating fonts every time you want to make a change.
  • Easily add only the icons you need as you go; keep those font files speedy!
  • Use your favorite SVG editor (Sketch, Illustrator, etc.) to create or tweak icons.
  • Much better Git versioning and collaboration. Merge in new icons others have added and track all changes clearly.

Setup

1. Requirements

You will need to install:

  1. Font Custom ruby gem. A couple of dependencies including FontForge will also be installed.
  2. Sass ruby gem version 3.3+, we need the SassScript maps feature.

2. File structure

Create the following folders and files:

├── fontcustom/
│   ├── fontcustom.yml
│   ├── templates/
│   │   ├── _font-icons.scss
│   │   └── _icon-font.scss
│   └── vectors/
└── scss/
    └── styles.scss

3. Prepare the fontcustom.yml config file

This file contains:

# Font Custom config: https://jaydenseric.com/blog/font-icons-like-a-boss-with-sass-and-font-custom
font_name: icons
no_hash: true
input:
  vectors: vectors
  templates: templates
templates: [_font-icons.scss, _icon-font.scss]
output:
  fonts: fonts
  _font-icons.scss: ../scss
  _icon-font.scss: ../scss

The paths are relative to the config file’s location. Tweaking this structure may give you headaches until a particular bug is fixed.

4. Prepare the _font-icons.scss template

/fontcustom/_font-icons.scss is not a Sass file. Font Custom will use this template to create a Sass file in the location configured (/scss/_font-icons.scss) each compile.

$font-icons: (<% @glyphs.each do |name, value| %>
  <%= name.to_s %>: "\<%= value[:codepoint].to_s(16) %>",<% end %>
);

5. Prepare the _icon-font.scss template

Again, this is a template; not yet an actual Sass file.

@font-face {
  font-family: Icons;
  src: url("data:application/x-font-woff;charset=utf-8;base64,<%= woff_base64 %>") format("woff");
  font-weight: normal;
  font-style: normal;
}

6. Prepare your main Sass file

In /scss/styles.scss, allow easy use of font icons in your main stylesheet by importing the two Sass partials, along with a nifty mixin:

@import "font-icons";
@import "icon-font";

@mixin icon($position: before, $icon: false, $styles: true) {
  @if $position == both {
    $position: "before, &:after";
  }
  &:#{$position} {
    @if $icon {
      content: "#{map-get($font-icons, $icon)}";
    }
    @if $styles {
      speak: none;
      font-style: normal;
      font-weight: normal;
      font-family: Icons;
    }
    @content;
  }
}

// The rest of your sexy styles here...

Usage

1. Add new icons to the project

To add a new icon, save it to /fontcustom/vectors as an SVG named what you want to call it by in your Sass.

I highly recommend square 32 × 32px SVGs with an accuracy of at least 3 decimal places.

The IcoMoon web app is the most convenient way to get new icons. Search from a huge range of great collections, select the ones you like and click the SVG download button. This will give you a nice zip of SVG files ready for you to drop into your project.

It’s always a good idea to optimize SVG with a tool like SVGO before use.

Here is what the project looks like with a few new icon SVGs:

├── fontcustom/
│   ├── fontcustom.yml
│   ├── templates/
│   │   ├── _font-icons.scss
│   │   └── _icon-font.scss
│   └── vectors/
│       ├── facebook.svg
│       ├── twitter.svg
│       └── heart.svg
└── scss/
    └── styles.scss

2. Run Font Custom

You must run Font Custom whenever you update your icons. In Terminal, navigate to the /fontcustom folder and run fontcustom compile. If you are doing a lot of work on your icons use fontcustom watch instead to automatically recompile any time a change is detected within the /fontcustom folder. watch seems to be a bit broken these days, so I tend not to use it much.

Our project now, with compiled files and folders:

├── fontcustom/
│   ├── fontcustom.yml
│   ├── fonts/
│   │   ├── icons.eot
│   │   ├── icons.svg
│   │   ├── icons.ttf
│   │   └── icons.woff
│   ├── templates/
│   │   ├── _font-icons.scss
│   │   └── _icon-font.scss
│   └── vectors/
│       ├── facebook.svg
│       ├── twitter.svg
│       └── heart.svg
└── scss/
    ├── _font-icons.scss
    ├── _icon-font.scss
    └── styles.scss

Note the new /fontcustom/fonts folder. We don’t need it since we are embedding the font in the CSS as base64 WOFF. Unfortunately, Font Custom always creates these files. You can safely delete the folder, or if you use Git just add it to your .gitignore file like I do:

fontcustom/fonts
.fontcustom-manifest.json # Ignore this temporary file too

3. Use the icons in the Sass

You are now ready to use the new icons throughout your Sass. Please refer to the Usage section of my detailed article about the icon Sass mixin for code examples.

IE8 support

To tailor the same workflow for IE8 support, skip the _icon-font.scss template and use a standard @font-face declaration referencing the actual font files Font Custom generates instead.