This is a card in Dave's Virtual Box of Cards.

Make a Web Font Subset

Page started: 2025-09-02
Page published: 2025-09-08

See also: Using and Debugging a Web Font

I’m not super into using Web Fonts because they’re one of those big and heavy things that too many websites abuse.

On the other hand, they are really cool, actually. And with Web Open Font Format (specifically WOFF2 with Brotli compression), they can be amazingly compact. Like, 40Kb for a whole font, which is incredible. (Just please, please use them judiciously.)

Using the Python fontTools (github.com) library, you can create your own subset of a TrueType Font (TTF) and turn it into a web font that is surprisingly small and covers just the glyphs you need to render on your page. (Licensing still applies, so make sure you use a free font or have the license to use it or make a subset.)

If you just need a few characters, you can make font files under 3Kb!

You’ll need a list of characters to export

In my case, I want to make a font that covers just the subset of emoji I’ve picked for a particular instance of my Emoji picking library, Faceclick.

The fontTools subset command can take a list of characters or glyphs in several different ways. Since I had over a thousand to list, I found the easiest way was to put them in a regular old UTF-8 text file and supply that at the command line.

Here’s a Ruby script in the Faceclick project that spits out the raw emoji text (you redirect it to a file to save it): maketxt.rb

Let’s look at a couple "Emoji fonts"

There’s a number of high-quality, free Emoji fonts available. Two I’d like to highlight are Noto and Twemoji.

I’ve got a table summarizing file sizes at the bottom of this page.

Noto Emoji

The Noto Emoji font contains all current emoji and comes with support for multiple font weights at under 2Mb. (Or you can pick just a particular weight, e.g. "regular", "bold", at 890Kb each, which isn’t quite as bad.)

The full Noto Color Emoji has extremely detailed glyphs and looks really great, but it’s much larger. With all font styles and all Emoji, the whole thing weighs in at 24Mb!

Mozilla Twemoji

I do want colored Emoji glyphs because they’re fun and they really stand out for my intended purpose, but I don’t want the file weight of Noto Color.

When I looked into which fonts were being used to render the Emoji on this contact sheet, with no web font loaded, Firefox showed that it was using a font called Mozilla Twemoji to display them.

It turns out "Mozilla Twemoji" is a color OpenType font from the Twemoji collection (originally from the "bird site"), which covers Emoji up to the Unicode 14.0.0 spec from 2021.

Released TrueType Font files such as Twemoji.Mozilla.ttf are available here:

Install fontTools

I installed fontTools on Slackware Linux with:

$ python3 -m pip install fonttools brotli lxml

And, later, on Arch Linux with:

$ sudo pacman -S python-fonttools

running fontTools "subset"

Documentation: Subset: Generate subsets of fonts or optimize file sizes (fonttools.readthedocs.io)

The command I’m going with for making a subset of a font using a text file containing the Unicode characters to export and saving the results as a web font in WOFF2 format is:

fonttools subset --text-file=<.txt> --flavor=woff2 <font file>

To convert the aforementioned three fonts out, here’s the commands I ran:

$ fonttools subset --text-file=myemoji.txt --flavor=woff2 NotoColorEmoji-Regular.ttf
$ fonttools subset --text-file=myemoji.txt --flavor=woff2 NotoEmoji-Regular.ttf
$ fonttools subset --text-file=myemoji.txt --flavor=woff2 Twemoji.Mozilla.ttf

If your font causes it, you can ignore the following message about an 'FFTM'.

WARNING: FFTM NOT subset; don't know how to subset; dropped

FFTM stands for "FontForge TiMe stamp table", which you can read about here: fontforge.org/docs) It’s not a standard font feature and fontTools simply doesn’t know what to do with it.

By the way, I first learned of this from Phil Gyford’s website: How to generate a subset of an emoji font using Python (gyford.com). Phil, in turn, credits Richard Rutter’s How to subset a variable font (clagnut.com).

Results

In terms of file size, this is what I got:

Font Original TTF Size WOFF2 Subset of 1,284 Emoji
Noto Color Emoji ("regular") 24,270 Kb 9,839 Kb
Noto Emoji ("regular") 890 Kb 410 Kb
Mozilla Twemoji 1,474 Kb 307 Kb

Here’s a cropped portion of Noto Color:

partial notocolor font sheet

But non-color Noto…​for some reason, not all of the black and white line art Noto fonts are showing up (the color ones are a fallback font). I tried this on two different computers with different operating systems and browsers and had indentical results. I’m really not sure what’s going on there and I don’t feel like pursuing it any further:

partial noto font sheet

But that doesn’t matter because my real goal is…​

The Twemoji subset font

Here’s a cropped screenshot:

partial twemoji font sheet

Files:

That’s it for making the subset font.

The adventure continues in Using and Debugging a Web Font.