Glyphhanger — a tool to subset and optimize fonts
- Published at
- Updated at
- Reading time
- 3min
I've been playing with variable fonts the other day and got excited about transitioning font weights without layout shifts.
But in the end, I had to conclude that a 785kB heavy variable font is too much for my lightweight blog. Especially, when I want to use this font only in a single demo component.
Nicolas Friedli pointed out that I can minimize the font's file size down to 322kB by using Glyphhanger — "the web font utility belt".
I've used Roboto
and it includes 826 characters and 948 glyphs. That's a lot and my blog is English, so I'd use less than 10% of these provided characters.
Glyphhanger lets you remove all these unused characters and glyphs.
# subset Roboto to Latin character set
glyphhanger --subset=roboto.woff2 --format=woff2 --LATIN
By subsetting roboto
to the Latin character set, I cut the number of included font characters and the resulting file size into more than half!
But after inspecting the subsetted font file with Wakamai Fondue, I discovered that I could probably squeeze out some more characters because I doubt I'll use any of these special characters either ÁÂÃÄÅÆÇÈÉ
.
# subset Roboto to ASCII character set
glyphhanger --subset=roboto.woff2 --format=woff2 --US_ASCII
By choosing ASCII
, I reduced the font to 95 characters and 121 glyphs, resulting in roughly 200kB. Success!
But now I was entering a dangerous territory because glyphs such as “
or …
had been excluded, too. I didn't want to add up with mixed or broken characters.
Luckily, Glyphhanger has a solution for this case, too. Use the --whitelist
argument to include the ASCII character set and additional glyphs in your optimized font.
# include ASCII and custom characters
glyphhanger --subset=roboto.woff2 --format=woff2 --US_ASCII --whitelist=…“”
So far so good! But what if you really don't want to waste any bytes and only deliver the needed font characters? Glyphhanger also lets you specify a page, and then evaluates all the used characters to subset a perfect font that doesn't waste any bytes on the wire.
# print all used codepoints
glyphhanger https://stefanjudis.com --string
# !"#%'(),-./0123456789:;?@ABCEFGHIJLMNOPQRSTUVWXYabcdefghijklmnoprstuvwxyz{}©—
# print all used codepoints with a specific font
glyphhanger https://www.stefanjudis.com --family="Roboto"
# ,.DHIabcdefghiklmnoprstuvwy
# evaluate and subset font depending on used characters on a page
glyphhanger https://www.stefanjudis.com/ --subset=roboto.woff2 --family="Roboto"
# Subsetting roboto.woff2 to roboto-subset.woff2 (was 765.65 KB, now 56.54 KB)
All this automatic font subsetting is pretty wild, but it allowed me to squeeze as many bytes out of Roboto as possible.
My little article component that used Roboto to explain a relative font weight axis (GRAD
) just got 700kB smaller by only including the characters in use!
I was even able to reduce its size down to 52kB by removing most of Roboto's font axes.
In conclusion: I highly underestimated how many bytes one can save by inspecting and subsetting fonts. The optimized Roboto variable font still includes all the custom axes and fancy variable font features, but especially for this single component, the page has become substantially lighter.
I'm still on the fence if I'll adopt custom fonts on this site, but this tool and trick are nothing but amazing!
Join 5.5k readers and learn something new every week with Web Weekly.