Reducing webfont size

When rebuilding this website, I wanted to have a proper logo. And with SEO and progressive enhancement in mind, I wanted it to be just text displayed in a specific font. Like images and every other assets of this blog, I also wanted to make sure every byte downloaded was useful.

A regular font contains all the alphabet, all 10 digits, and a lot more characters. My website's name only contains 8 different characters. How to optimize the webfont to only include the needed characters, and nothing more?

There are 2 cases, whether you use a Google Font or not.

Subsetting a Google Font

#

You'll need to use the CSS2 API from Google Fonts. You just need to ad a text= query parameter to the stylesheet link in your HTML head.

<link
href="https://fonts.googleapis.com/css2?family=Noto+Sans&text=hack%20%26es"
rel="stylesheet"
/>

Make sure you urlencode all the characters.

Be careful, this text parameter will apply to the whole list of fonts you specify in the font call. So if you use several fonts but want to subset only one, you'll need to separate your font calls.

See the Google Fonts CSS2 API documentation for more information.

Subsetting any other font

#

Let's use fontTools, a Python library and CLI tools to manipulate font files. One of these tools is pyftsubset, which allows to keep a subset of characters in the font file and remove everything else.

First, install fontTools. Since webfonts should now be in WOFF2 format, fontTools will need the extra woff feature. And since WOFF2 uses brotli for compression, make sure to install it via your system package manager before.

pip install fonttools[woff]

Now let's use pyftsubset:

pyftsubset \
"original.woff" \
--text="hack & cheese" \
--flavor="woff2" \
--no-hinting \
--desubroutinize \
--name-IDs="" \
--layout-features="" \
--output-file="subset.woff"

Options, explained:
"original.woff": original font file
--text="hack & cheese": the list of characters we want to keep
--flavor="woff2": export as a WOFF2 file
--no-hinting: remove instructions on how to render in low pixel sizes
--desubroutinize: optional, it may make the file smaller
--name-IDs="": strip all naming metadata
--layout-features="": remove all layout features, such as kerning
--output-file="subset.woff": resulting optimized webfont file

All the pyftsubset options can be found in the documentation.

You now have the smallest possible webfont file, that still works perfectly in your browser!