Skip to main content
Charlie Chao (go home)

Font Icons Workflow with Sketch and Grunt

Published

2 rows and 4 columns of icons

Font icons, a scalable and flexible way of displaying flat monochromatic glyphs, is commonly leveraged by developers in websites and web apps. However, creating one can be quite a hassle since this technique started out as a hack and there are no official ways of doing it. There are several powerful tools like IcoMoon and Fontello which make it easier to manage and convert your vector icons into web fonts. But, they require you to be in the app and do some manual work such as uploading your SVGs and downloading the compiled assets into your project folder every time you make a change.

Because of this friction, I wanted to streamline the process without depending on a separate tool to manage the icons. By using SketchSketchTool and Grunt, I’ve devised a way of being able to curate and design the icons in Sketch, and then conveniently transforming them into usable web fonts in one swoop of a build script. This article will show you my workflow in creating a simple icon set for the web as well as how to automate the generation of font icons for your front-end project.

Note: You can download the final source project that demonstrates the front-end setup as you follow along.

Icon Metrics

Icons laid out on a grid in Sketch

Before creating an icon set document in Sketch, it’s important to consider the grid size of the icons you’re planning to use on your site. Try to tackle the worst-case scenario by choosing the smallest intended size in order to account for low-resolution screens.

Scaled icons in a 4x4 grid next to optimized icons in a 4x4 grid

In addition, the size should depend on the body text size as most icons are placed inline with the text such as inside a button or as part of a navigation item. Using the same height makes them easier to align on the baseline (e.g. 16x16 for 16px font size).

You can also have multiple starting sizes for your icons. The idea is that when you scale them up, you would use a multiple of the base size to maintain their best qualities (e.g. 16x16 → 32x32 → 48x48 or 24x24 → 48x48 → 72x72).

Finally, be aware of where the ascent and descent lines are in your icons. By default, it will be a 2 pixel margin from above and below for size 16, and a 3 pixel margin for size 24. These metrics can be adjusted in the build script discussed later on.

A 24x24 icon and a 16x16 icon side-by-side, with the ascent and descent line overlaid

Layer Arrangement

Below is the typical layer arrangement I use for each of my icons:

Screenshot of Sketch layers: Icon Group, Path, Bound, Slice

Icon Group – Contains the paths, preferably combined using boolean operations (union, subtract, etc). To ensure minimal issues when it is converted from a SVG to a font glyph, check that all…

  • strokes are vectorized (Layer → Paths → Vectorize Stroke)
  • texts are converted to outline (Type → Convert Text to Outlines)
  • transformed paths (e.g. flipped or rotated) are flattened (Layer → Paths → Flatten).

Bound – A hidden rectangle that defines the boundary of the icon. It exists for the purpose of keeping the icon size intact when pasting the icon into your mock ups.

Slice – The export slice set to 1x SVG. Its name will determine the CSS class name that you will use in your HTML (e.g. .icon-home-24).

Installing Sketchtool

The good people at Bohemian Coding created a super useful command-line utility called SketchTool that lets us export artboards and slices outside of Sketch. Better yet, it doesn’t require Sketch installed in the system, so if the developer’s machine doesn’t have it, the tool will still work.

GIF of sketchtool being installed in Terminal

Download and extract it. Open up Terminal to the folder and run bash install.sh. Then run sketchtool to confirm that it is installed.

Exporting and Generating the Fonts

With the icons properly setup in a Sketch document and SketchTool installed, it’s time to configure Grunt to generate the fonts for us. Two Grunt tasks will be used: grunt-shell and grunt-webfont (please follow the installation instruction based on your OS).

The code below is the full Gruntfile. Upon running its default task, it will run SketchTool through grunt-shell to export all the icons from the Sketch document as SVGs into a folder. Then it will use grunt-webfont to package the vector files into web-ready fonts as well as generating the required CSS and an HTML preview of the icon set.

module.exports = function(grunt) {
grunt.initConfig({
shell: {
exportIcons: {
command: 'sketchtool export slices assets/icons.sketch --output=assets/icons/'
}
},
webfont: {
icons: {
src: 'assets/icons/*.svg',
dest: 'src/fonts/',
destCss: 'src/css/',
options: {
font: 'icons',
fontHeight: 96,
normalize: false,
ascent: 84,
descent: 12,
destHtml: 'assets/',
templateOptions: {
classPrefix: 'icon-'
}
}
}
}
});
grunt.loadNpmTasks('grunt-webfont');
grunt.loadNpmTasks('grunt-shell');
grunt.registerTask('default', [ 'shell:exportIcons', 'webfont:icons' ]);
};

Let me walk you through some important lines.

The shell:exportIcons task is pretty straightforward. It runs SketchTool in the terminal and exports all the slices from assets/icons.sketch into the assets/icons/ folder based on the export settings of the slices in the document.

The webfont:icons task has some interesting options to be aware of. Under options, the fontHeight is set to 96, which is a common multiple of 16 and 24. This allows the icons we’ve created to co-exist in a single font face without encountering metric-related issues. You’ve probably noticed that it’s not the least common multiple (48) because for whatever reason, a smaller value can cause slight hinting problems. Nevertheless, try to keep it small to shave off the extra bytes in the compiled font files.

The ascent and descent properties must always be positive values, and are measured from the bottom of the glyph boundary.

normalize is set to false here to override a default behaviour with the font engine that makes the glyph width as wide as the paths inside. We want the width to match the height to avoid inconsistency with the icon size.

And that’s it! Run grunt from the Terminal and the whole process is blasted through in seconds. Now you can reference the generated CSS your HTML and apply the icon classes to your elements.

GIF of Terminal running grunt command

2 rows of buttons with icon lined up with their respective labels

I’ve created a sample project with a Sketch document and the build script right here. Try it out, modify it, and see if this workflow can help you streamline font icons creation for your projects 🙂

Resources

Charlie Chao is a product designer who writes about design, development, and productivity. Chat about this article on Thread and subscribe to the RSS feed for more updates.