Conversion of fonts to WOFF/WOFF2 and font subsetting with Glyphhanger

To use web fonts with wide browser support, we need the font files in .woff and .woff2 format. Who does not care about Internet Explorer, Safari on Mac OS before Sierra, and a few mobile browsers can choose only .woff2 (there are tables with the browser support of the two formats on Can I use).

In this post, I show how to use the command line tool Glyphhanger to convert .ttf files to .woff and .woff2 and subset fonts to remove unused characters.

Update from July 22, 2018: Today I tried to install Glyphhanger and got an error that Chromium could not be downloaded. I found a fix for that in a GitHub issue and updated the post accordingly.

Why all the effort? There are services like Google Fonts or Typekit...

That is right. But if you use fonts via third-party services, user information (at least the IP address) are sent to this service, and that could be problematic with the upcoming GDPR.

Loading fonts locally from the web server is the safer variant.

What is Glyphhanger?

The project’s GitHub repo describes it as »web font utility belt«: it comes with various features that make working with web fonts easier. In the blog post »It’s Dangerous to Go Stallone. Take Glyphhanger«, Zach Leatherman introduces the tool that he created for the Filament Group.

Glyphhanger’s features in short:

  • creating WOFF/WOFF2 files from .ttf.
  • subsetting fonts
    • by specifying certain Unicode characters(ranges).
    • by specifying one or more URL(s) from which the characters of the content are used as subsetting value. For that, there is also a crawler feature, so that linked pages of the website are also analyzed. Besides that, it is possible to provide a font-family value, to only get the characters that are inside of elements with that rule. Via a whitelist, you can specify characters that should be part of the subset in any case.
  • convert a string to Unicode ranges.
  • convert Unicode ranges to a string.
  • CSS rules for using the subset.

Installation of Glyphhanger

Preliminary note: I installed it on Windows 10 with the Windows Subsystem for Linux. For the installation of fontTools (if I remember correctly) it was necessary to run Bash on Ubuntu on Windows as administrator.

To install Glyphhanger, run the following command (using --unsafe-perm=true --allow-root was necessary for me with Ubuntu on Windows 10. Without it, I got an error that Chromium cannot be downloaded):

npm install -g glyphhanger --unsafe-perm=true --allow-root
Code language: Bash (bash)

To use the subsetting feature, you need the Python library fontTools, which can be installed with the following commands from the readme of the Glyphhanger project:

pip install fonttools # Additional installation for --flavor=woff2 git clone cd brotli python install # Additional installation for --flavor=woff --with-zopfli git clone cd py-zopfli git submodule update --init --recursive python install
Code language: Bash (bash)

After that, Glyphhanger is ready to use.

Converting .ttf files to .woff and .woff2

First a note: the font license must, of course, allow the font to be used as a web font, be converted and modified (subsetting). The font license should present in the downloaded folder.

If you downloaded such a font, for example, from Google Fonts, switch to the command line and navigate to the folder with the font files. To convert them to WOFF and WOFF2 files without subsetting, the following command is enough:

glyphhanger --formats=woff2,woff --subset=*.ttf
Code language: Bash (bash)

You should get back messages from the command line while the tool is working, like the following:

Subsetting NotoSans-Black.ttf to NotoSans-Black-subset.woff2 (was 458.75 KB, now 162.26 KB)
Code language: Bash (bash)

Depending on the number of font files (and probably the size of the individual files), this may take some time. Afterward, you have files, which you can integrate via the @font-face rule.

Useful for that: besides the new font files, you will notice CSS files, that contain examples of the rules to load the fonts:

@font-face { src: url(NotoSans-Black-subset.woff2) format("woff2"), url(NotoSans-Black-subset.woff) format("woff"); }
Code language: CSS (css)

Font subsetting

Now the subsetting of fonts, the removal of unused characters from the font, to make the files smaller. Glyphhanger brings with --US_ASCII and --LATIN two presets for the subsetting. For my conversion from Google Fonts to self-hosted fonts, I used another solution.

The Google Fonts API URL for Noto Sans, for example, looks like this, when only loading the regular style:

Accessing this URL will return several @font-face rules for various character sets, including the specific unicode-range details (with that, supporting browsers will only download the font file if needed). I used the values of unicode-range for the --whitelist parameter of Glyphhanger and created one subset after the other for the different character sets.

The command for creating the cyrillic-ext subset of Noto Sans, for example, looks like that:

glyphhanger --formats=woff2,woff --subset=*.ttf --whitelist="U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F"
Code language: Bash (bash)

I used the @font-face rules from the Google API, modified the url() values, added the url() of the WOFF file, and used the unicode-range values from the Glyphhanger CSS files (those are shortened by (hopefully) unnecessary characters, for example, U+0460-052F becomes U+460-52F).

And with that, we now have optimized font files for loading from the website’s server. Like said, the tool comes with various other options, like using the characters from a Website for the subsetting – that could be handy, for example, if it is a static website, that will not have content changes in the foreseeable future.

Leave a Reply

Your email address will not be published. Required fields are marked *