Skip to main content
Dublin Library

The Publishing Project

Font formats for the web and converting from one to another

 

Using fonts on the web has a longer story than many would think.

The @font-face at-rule has been around since the early days of the web. Initially, there were no fonts on the web... the goal was to share documents, not to produce the polished documents that we see today.

In the beginning, web browsers relied on locally installed fonts both for performance (the modems of the time would take forever to download a font).

We could use any of the pre-defined fonts:

  • Andale Mono
  • Arial
  • Arial Black
  • Comic Sans MS
  • Courier New
  • Georgia
  • Impact
  • Times New Roman
  • Trebuchet MS
  • Verdana
  • Webdings (Webdings)

There were several methods for embedding fonts that didn't catch on like TrueDoc in 1996, an outline font standard developed by Bitstream, or Embedded OpenType (EOT) in 1997.

CSS 2.0, introduced in 1998, included support for @font-face in pretty much the same way as it does now but browsers were afraid of being seen as contributors to font piracy so they didn't implement it when it was first released.

It wasn't until 2008 that browsers (re)introduced @font-face with support for different formats:

  • The beta version of Safari 4 implemented @font-face support for TrueType fonts
  • The beta version of Firefox 3.1 implemented support for both TrueType and OpenType

Other browsers continued to support separate formats which eventually led to the "bulletproof @font-face syntax", dating back to 2009 in Paul Irish's Bulletproof @font-face Syntax

in 2009, Small Batch announced the Typekit project, a subscription-based ‘middleman’ service for designers and developers, which allowed safer embedding of fonts via the @font-face CSS declaration and some JavaScript.

We now have a variety of services like TypeKit (acquired by Adobe and now known as Adobe Fonts). The biggest one is Google Fonts

Things have improved in terms of common support. All modern browsers except IE and Opera Mini now support WOFF2 fonts.

The four most used formats for fonts are:

  • TTF (True Type Fonts)
  • OTF (Open Type Fonts)
  • WOFF (Web Open Font Format 1.0)
  • WOFF2 (Web Open Font Format 2.0)

What format you use depends on the browsers you must support.

Not all fonts are available in all formats and I've found out over time that I have to do manual conversions, usually from TTF or OTF to newer formats.

I will run through the process both to illustrate the tools and process I use to compress fonts from TTF to WOFF and WOFF2

Getting Started #

I downloaded Open Sans from Google Fonts as the basis for the compression examples.

WOFF #

To convert to WOFF, I use the ttf2woff utility, available as a Node package.

To install it, run the following command:

npm i -g ttf2woff

To convert the font to WOFF, use the following command, replacing both instances of the font name with the font you're working with.

ttf2woff \
OpenSans-VariableFont_wdth,wght.ttf \
OpenSans-VariableFont_wdth,wght.woff

and then do the same thing with the italic version of the variable fonts:

ttf2woff \
OpenSans-Italic-VariableFont_wdth,wght.ttf \
OpenSans-Italic-VariableFont_wdth,wght.woff

If you're not working with variable fonts, you can run the same command for each individual font face.

ttf2woff OpenSans-Bold.ttf OpenSans-Bold.woff
ttf2woff OpenSans-BoldItalic.ttf OpenSans-BoldItalic.woff
ttf2woff OpenSans-Italic.ttf OpenSans-Italic.woff
ttf2woff OpenSans-Regular.ttf OpenSans-Regular.woff

WOFF2 #

WOFF2 is an evolution of the WOFF format that provides further savings in terms of file size.

To convert the font to WOFF2 I'm using Google's WOFF2 Reference Implementation

Install the library via Homebrew or your platform-specific package manager with the following command:

brew install woff2

And run the compression tool with the following commands:

woff2_compress \
OpenSans-VariableFont_wdth,wght.ttf
woff2_compress \
OpenSans-Italic-VariableFont_wdth,wght.ttf

These are the results of compressing our regular variable font with the different formats:

Font Format Size
OpenSans-VariableFont_wdth,wght TTF 530KB
OpenSans-VariableFont_wdth,wght WOFF 345KB
OpenSans-VariableFont_wdth,wght WOFF2 280KB

And these are the results for the italic variable font. Note how the values for all formats are slightly larger in this example.

Font Format Size
OpenSans-Italic-VariableFont_wdth,wght TTF 580 KB
OpenSans-Italic-VariableFont_wdth,wght WOFF 389KB
OpenSans-Italic-VariableFont_wdth,wght WOFF2 310KB

If we also take into consideration that WOFF2 is supported across all browsers, except IE and Opera Mini, it is safe to say that, size-wise, WOFF 2 is the best format to use.

Subsetting #

We converted the fonts to WOFF2 and did the best we could do without resorting to exotic compression tools like Brotli or Zopfli.

There is one more thing we can do to improve the file size of the fonts: subsetting.

SUbsetting is the process of taking a large font file and creating smaller font files, with fewer characters or OpenType features.

Subsetting to the Latin character set #

For this demo, we'll just reduce the characters in the font to those necessary for Latin scripts using Glyphhanger to generate both WOFF and WOFF2 versions of the subset fonts.

glyphhanger --latin \
--subset=OpenSans-VariableFont.woff2  \
--formats=woff-zopfli,woff2

And the equivalent command for the italic variable font:

glyphhanger --latin \
--subset=OpenSans-Italic-VariableFont.woff2  \
--formats=woff-zopfli,woff2

Subsetting to ASCII #

Perhaps the most aggressive subsetting available that doesn't match pages is subsetting to the US-ASCII character set. This will handle English and no other language since ASCII was created to represent characters in the English alphabet.

Running Glyphhanger to subset to the US_ASCII character set looks like this:

glyphhanger --US_ASCII \
--subset=OpenSans-VariableFont.woff2  \
--formats=woff-zopfli,woff2

The equivalent command for the Italic font:

glyphhanger --US_ASCII \
--subset=OpenSans-Italic-VariableFont.woff2  \
--formats=woff-zopfli,woff2

This produces the smallest font size by a large margin as shown in the following table

Font Subset Format Size
OpenSans-VariableFont Latin WOFF + Zopfli 330KB
OpenSans-VariableFont Latin WOFF2 276KB
OpenSans-VariableFont ASCII WOFF + Zopfli 74KB
OpenSans-VariableFont ASCII WOFF2 63 KB
OpenSans-Italic-VariableFont Latin WOFF + Zopfli 373KB
OpenSans-Italic-VariableFont Latin WOFF2 310KB
OpenSans-Italic-VariableFont ASCII WOFF + Zopfli 83KB
OpenSans-Italic-VariableFont ASCII WOFF2 70KB

However unless you're absolutely sure that you will use English only with no phrases from other Latin languages like Spanish or French then you shouldn't use the ASCII subset; otherwise, I would recommend the Latin Subset.

The sizes will also vary with the font or fonts you use. There are fonts that deliver a single variable font to cover all possible styles and variations. These fonts will be larger overall, but the larger size is offset by it being a single file to download.

Edit on Github