Font Compression and Me

programmatic-design by Bast on Wednesday March 17th, 2021

So, for those of you who've seen this blog before I post this (and thus update the fonts), I've been using Times as my font of choice. I've had flings with Verdana–should I use it, should I not use it–but ultimately I felt Times was the simplest choice.

It needed to be a web font at the start of the project (no included font files! to go with my inline css)–which limited me to roughly these fonts:

Serif: Georgia or Times (New Roman)

Sans-Serif: Arial, Helvetica, Tahoma, Verdana

And not all sources agree on which fonts actually work for this. Notably, w3schools in their "CSS Web Safe Fonts" article suggests fonts that aren't present on my up-to-date mac laptop, notably, Garamond, which historically was available but (presumably due to licensing issues) is not actually available for rendering in arbitrary applications like web browsers. Which is all well and good, but Garamond doesn't render in firefox on my laptop. And that's not an edge case, so it's out of the running.

On top of that, I come from a history of reading books. I like serif fonts. I want a serif font for my blog. But as you can probably see already, there are only two choices here if I don't want to include a font. Georgia, which I'm not a fan of, and Times, which I picked initially. But I'm honestly not really a fan of Times either.

So, off I go on the adventure of including a font into my pages. Step one is finding a good font–at the moment I've settled on Quivira, which is a now public license font made by Alexander Lange (thank you!), which I've historically used and quite liked in my A-Dark-Room inspired incomplete game Foxes.

While it does have some kerning oddness, I actually like that somewhat. It makes it feel more real. And while I will probably have to adjust some of the background colors on the page to make it fit right I think it may be a step in the right direction. Hopefully.

One of the reasons I chose Quivira at the time was because of its high glyph support deep into the interesting parts of unicode that I could use for custom characters for a void-y effect, like 🝟 or πŸœ›, or πŸ€πŸπŸ‚, 🜾, for example. They're all thematic, pleasant to use, pretty, and make for good "magic" glyphs (most come from the unicode alchemical code blocks). But because of this, the font is actually somewhat heavy–a whopping 1.5mb OTF font file. For a website that's a lightweight, speedy blog, that isn't going to work as-is.

Well, so, where's the inefficiency? Clearly I don't need all 1.5mb of glyphs for normal usage? Absolutely not! Nowhere near that, in fact. I only use about 92 characters normally (A-Za-z0-9 and casual special like (), [], -, etc). If it's not on my keyboard (and excluding this post, which is special!) I don't use it. I don't have alternate language translations (and if I did, I'd serve up a different font file with the solution I've used), so I have no use for accents, combining characters, or any of the other thousands of glyphs I would be serving with the naΓ―ve solution (oh no, I used another one. Well, it's only going to be in this post which has a bigger font export anyway).

Ok, so we've established I don't need all the glyphs. This is good, because there exist tools usable to strip unused glyphs from fonts and otherwise compact them. In addition, the OTF format is somewhat old at this point (1996!) and doesn't have a lot of the modern compression support stuff like, say, woff2 has (brotli and co). Which is the standard these days. It's also not supported on some legacy systems like older IE or opera mini. But I already don't support those, and have no desire of doing so, and the font support of OTF is not much better.

My tool of choice (python!) is fontTools, which, in addition to a bunch of library functionality and more, also comes with pyftsubset which does exactly what I'm looking for. Provide it a text file with glyphs, a font file, and a target, and it will strip out the extras and convert it to woff2 for me.

For normal posts (where I don't provide examples of high-unicode glyphs) the font comes in at a nice 6kb in size, 7kb when included as base64 in the css to skip a request. For posts like these I decided to keep the entire library of "magic" glyphs I use, so it comes in at 22~25kb instead. That's basically nothing compared to the 1.5mb–1.5% for the larger, 0.4% for the smaller, a staggering 250x size reduction.

So, I call that a success! Custom font, minimal impact. It's feeling like it's not actually worth it to split it out into a separate file, just like the css–it's just too small. The whole page is weighing in at around 40kb, of which even less (~13kb) is even transferred, with the font included. That's not that many packets, and the http request overhead, not to mention TLS, probably weighs more than that at this point!

( And, of course, when I finally automate the font generation I end up realizing that - and _ were being rendered with the system font instead because I forgot them in my glyphs file. Ah, such is the cost of progress. )