Webfonts

Tutorial
by Rainer Erich Scheichelbauer
en fr zh

17 August 2022 Published on 16 February 2019

Whenever you want to use custom fonts on the web, you need webfonts. And whenever you make webfonts, file size will be your main concern. Learn how to properly create WOFF and WOFF2 fonts, plus some neat tips as a bonus.

Needless to say, the smaller the better. A well-subsetted single-script webfont should clock in below 20K, and therefore, load fast.

Format overview

I told you above that file size is the primary issue. Number two on the list will be browser support. Unfortunately, not every web browser can handle every webfont file format. Glyphs can produce four kinds of webfonts: WOFF, WOFF2, and plain OpenType fonts (TTF/OTF). Here is a quick overview:

  • WOFF: Web Open Font Format. Longest supported format, necessary for legacy browsers. Chrome 5, Firefox 3.6, IE9, Edge, Safari 5.1, Opera 11.1, Android WebKit 4.4, and all respective later versions. More info about WOFF support.
  • WOFF2: Web Open Font Format 2. Best compression, and wide support in current browsers. Chrome 36, Firefox 39, Safari 10 (macOS 10.13 High Sierra and iOS 11 and later only), Edge 14, Opera 23, and all current Android browsers; not supported on Opera Mini and BlackBerry. More info about WOFF2 support.
  • Plain OpenType: OTF and TTF. Fallback format for very old browser versions. that did not support WOFF back then. Chrome 4 (0%), Safari 3.2–5.0 (macOS and iOS, 0%), Firefox 3.5 (0.01%), Opera 10.1–11.0 (0%), Android Browser 2.2 (0%). More info about TTF support.

You can safely ignore Plain OpenType. Yes, it does not hurt to implement them, but hey. As of this writing, not even 0.02% of web browsing may be done in browsers that necessitate these formats. Probably even less by the time you are reading this. In other words, focus on WOFF and WOFF2. Now, read on.

Exporting webfonts

Sure enough, to export the fonts you have set up in File > Font Info > Exports, you simply choose File > Export (Cmd-E) and pick the OTF option in the top row. You are presented with this dialog sheet:

You basically need to make three decisions:

  1. Outline flavour: OpenType/CFF vs. TrueType. The radio buttons determine in which outline format the fonts will be exported. TrueType-based fonts use components for keeping the filesize small, PS-based fonts use a technology called subroutinisation. Complex outlines cannot be subroutinised. Windows has performance problems with complex PS outlines, and sometimes you will see a difference in screen rendering, especially with hinting (see following point). You may need to try both, compare file sizes and rendering quality, and then decide.

  2. File format: .ttf/.otf, .woff, .woff2. The file formats in which the files will be exported, as discussed above. The option .ttf/.otf (depending on the outline flavour) are what is referred to as the Plain variant, in case you wondered. You want .woff and .woff2.

  3. Autohinting: if activated, ttfAutohint will be used on TT-flavoured fonts, and Adobe’s autohinting algorithm will be applied to PS/CFF-falvoured fonts, respectively. Complex fonts cannot be hinted.

  4. Remove Overlap: always on for shipping fonts, and for testing screen rendering. Only consider turning it off in order to speed up the export process if you are testing for character set and OpenType features. See Pro Tip below.

And, well yes, the fourth decision, the Export Destination, lets you preset a n export folder, which spares you the extra save dialog that follows otherwise. That can significantly speed up your export process, especially if you find yourself reexporting a lot in your quest to squeeze another kilobyte out of your WOFFs. All you need to export again is to press Cmd-E and hit the Return key.

Custom parameters

You can use the following parameters either in File > Font Info > Exports, or in a .glyphsproject file.

  • Webfont Formats: This allows you to specify which formats will be exported of the instance in question. You must use this parameter if you are outsourcing webfont production into a .glyphsproject file. Always Pick WOFF and WOFF2 unless you know what you are doing. And maybe throw in legacy EOT and Plain TTF files.
  • Webfont Only: Will fiddle with the tables inside the font in a way so that a rogue user will have difficulties reverse-engineering the OTF or TTF from the webfont. However, we do not recommend this. Use this parameter only if your client insists on this as an additional safety precaution.
  • Remove post names for webfonts: Removes glyph names in the webfont export, resulting in slightly smaller file sizes. may make a difference if you have a lot of dot-suffixed glyphs (for OT features), causing long production names.
  • Save as TrueType: Forces the TrueType option of the export dialog.
  • Autohint: Forces the Autohinting option of the export dialog.

But wait, there are more custom parameters available for your webfont geekery. Read on.

Subsetting

Subsetting refers to the removal of (unnecessary) glyphs from the font, thereby making the font a little smaller in terms of filesize. There are basically two mutually exclusive ways to achieve subsetting in Glyphs: either specifying which glyphs you want to keep, or which glyphs you want to get rid of. In both cases you take care of the subsetting with a custom parameter in File > Font Info > Font, or File > Font Info > Exports, or in a .glyphsproject file:

  • Remove Glyphs: You supply a list of glyph names to specify which glyphs will not make it into the exported webfont. Simply type out all glyph names, separated by newlines.
  • Keep Glyphs: same as above, except this time you specify which glyphs you want to export. All other glyphs in the font not mentioned in this parameter will not be exported.

In both cases, you can speed up things by using the Copy Glyph Names > One per Line command from the context menu in the Font tab (Cmd-Opt-1). And then paste your clipboard content into the parameter value. The only glyphs you cannot remove are .notdef and space.

And you can use the asterisk (*) as a wildcard, both at the beginning and end of a word. E.g., you may want to write ord* instead of spelling out ordfeminine and ordmasculine, or *.ss05 for all stylistic set 5 glyphs, or even *.ss* for all stylistic sets.

Even better, there are also key wildcards available. They allow you to add complete categories, subcategories and even scripts to the list of glyphs to be removed (or kept). A key wildcard consists of the case-sensitive glyph info key (script, unicode, category and subCategory), followed by an equals sign, which in turn is followed by an appropriate value for the key. Say you want to get rid of all Greek letters, all lowercase letters and all figures, so you add these lines to your Remove Glyphs parameter:

script=cyrillic
subCategory=Lowercase
category=Number

And you can combine the key wildcard with the asterisk. E.g., in order to delete all glyphs with Unicode values from U+0300 to U+04FF, you would add this to the parameter value:

unicode=03*
unicode=04*

OK, now that we have the tools for subsetting in our hands, what do we get rid of? Here are a few inspirations:

  • Small caps: *.sc
  • Figure variants: *.tf *.tosf *.osf *.lf
  • Stylistic sets: *.ss*
  • Character variants: *.cv*
  • Ornaments: *.ornm
  • Very rare, deprecated, unused or untypable letters: AEacute aeacute Aringacute aringacute IJ ij napostrophe Oslashacute oslashacute
  • Localizations and compatibility glyphs: Tcedilla tcedilla Ldot ldot
  • Rare symbols: lozenge paragraph currency florin logicalnot infinity integral product summation radical micro partialdiff perthousand registered trademark bar brokenbar dagger daggerdbl estimated apple
  • Letters for languages that are not necessary on the website it is intended for. E.g., on that page dedicated to Dutch literature, you will very likely not need those extra glyphs that are only used in Esperanto, Ccircumflex ccircumflex Hcircumflex hcircumflex Jcircumflex jcircumflex.
  • Letters of scripts that are not needed for the purpose of the font. Bulgarian webpage? You will need Cyrillic, maybe a little Latin, but probably not the Greek parts of the font, so you go: script=greek.

Anything else? Sure, but your mileage may vary. So, after export, always verify the glyph set and see if there is one more glyph you can take out. To do that, it is a good idea to export and test often. You can quickly open your font in apps like OTMaster or FontTableViewer, or on test pages like Wakamai Fondue or FontDrop, see further below for more info on those. Did an unnecessary glyph still make it through the limbus? It will not go unnoticed.

Feature subsetting

If you have done subsetting, and you export, you may end up with an error dialog like this:

The dialog reports an unknown glyph in the feature code. It mentions a glyph name (e.g., brevecomb and other combining accents in this example), and the exact spot: which line inside the font’s features (line 20 in this example), and which line inside which feature (line 2 in ccmp in this case). What most likely caused the error is a glyph name that still appears in your feature code but points to a glyph that is removed in the process of subsetting. In other words, the feature code in File > Font Info > Features is not in sync with the glyph structure in the subsetted instance.

If the feature in question is an automatic feature, this should not have happened in the first place. But it can happen if you have some complex custom parameter stuff going on. In that case, you may need to force the automatic update, simply by adding this custom parameter to your instance, and activating its checkbox, of course:

  • Update Features: force-refreshes all automatic OpenType feature code (including classes and prefixes) if enabled.

If, however, you have non-automated manual feature code, you may want to consider one of these parameters:

  • Remove Prefixes: takes a list of prefix names and deletes them during export.
  • Remove Classes: takes a list of OT class names (without the preceding at sign), and deletes those at export.
  • Remove Features: takes a list of four-letter OT feature tags, and deletes the respective features at export.
  • Replace Prefixes: supply the name of a prefix as it appears in the sidebar, followed by a semicolon, followed by new code, which is inserted at export time instead of the original code.
  • Replace Classes: supply the name of an OT class (without the preceding at sign), followed by a semicolon, followed by new code, which is inserted at export time instead of the original code.
  • Replace Features: supply the four-letter feature tag of a Feature, followed by a semicolon, followed by new code, which is inserted at export time instead of the original code.

More file size reduction

Experience shows that the most significant reductions are achieved by subsetting, but there are more ways to squeeze another kilobyte or two out of your WOFFs. To find out what causes the most weight gain in your webfont, see how big the tables are in your WOFF. The best way to do this is to download and install fonttools, and list all font table by running ttx -l fontname.woff in Terminal. Or better, you type ttx -l followed by a space, and then drag the WOFF into the Terminal window, which inserts its file path, then press Return. If everything went fine, you will get a list of tables similar to this:

    tag     checksum    length    offset
    ----  ----------  --------  --------
    CFF   0x9C30A665     29398      2992
    GDEF  0x3C093D1F       189     32392
    GPOS  0x15445ACD     13356     32584
    GSUB  0x42EA82BB      1429     45940
    OS/2  0x68B4820A        78      1372
    cmap  0x8F4E4BFE      1042      1928
    head  0x12AB135E        52       292
    hhea  0x066A05BF        32      1340
    hmtx  0x1BC61668       994       344
    maxp  0x02435000         6       284
    name  0x76A3CF96       475      1452
    post  0xFFB80032        19      2972

Look at the length column: You can tell that the table with the tag CFF (Compact Font Format, with PS outlines) takes up the most space, closely followed by GPOS (glyph positioning). CFF, cmap and hmtx are directly influenced by the number of glyphs in the font, while GDEF, GPOS and GSUB get their gravy from all OT features (including kerning) in your font. CFF is also where the PostScript hinting info is stored.

Let’s take a look at a typical TT-based webfont:

    tag     checksum    length    offset
    ----  ----------  --------  --------
    DSIG  0x00000001         8     14124
    GDEF  0x01C701B8        28       384
    GSUB  0x4C1A4D0D       492       412
    OS/2  0x697CB056        76       904
    cmap  0xEFD48A4D       628       980
    cvt   0x0CE0037F        40     12208
    fpgm  0x9E3611CA      1729     12248
    gasp  0x00000010         8     12200
    glyf  0xE8E7B58E      8718      1608
    head  0x112593E0        53     10328
    hhea  0x088C054F        32     10384
    hmtx  0xDBC80FBB       336     10416
    loca  0x668F76DC       216     10752
    maxp  0x033E0F25        32     10968
    name  0x6F5D0BBB       348     11000
    post  0x55CEA4FD       852     11348
    prep  0x6846C89C       143     13980

In TrueType fonts, outline info is stored in the glyf table, typically the largest table in the font. TT hinting info is spread across prep, gasp, cvt, and fpgm.

So, depending on where you count the most bytes, you can make an informed decision on which file reduction steps you want to take next. Here are a few suggestions.

Reduce hinting:

Are you exporting TT-based webfonts and using the Autohint option? Add a TTFAutohint options parameter to your instance, and fine-tune where possible:

  • Limit your hinting: ttfAutohint can be limited to a certain PPM size. Try to keep it as low as possible, only employ it for sizes where it really makes a difference. So, keep your Hinting Limit low, e.g. below 50, and employ a small Hint set range that encompasses only the most important PPM sizes, e.g. 12 to 32.
  • Avoid extras such as Hint composites, Adjust subglyphs, Detailed info, and ttfa table. They are usually not needed, and can take up quite a bit of space.
  • Activate No Autohint Info. It is not much, but hey.

If you are exporting CFF-based webfonts, perhaps only apply hinting to the glyphs you need most. Consider a custom parameter called Disable autohinting for glyphs and supply a list of glyph names that should be excluded from hinting.

If your font is for catering only or mainly to Apple hardware: Consider removing hinting altogether, or perhaps also supply an unhinted version that is delivered only to Apple devices. If your web admin knows how to do that, of course.

Reduce kerning:

A lot of kerning will evaporate once the involved glyphs have been removed. But the kerning that is left may still be a burden on the file size.

Get rid of smallest kern pairs. Anything up to a certain threshold value can go. Depending on the design, that can be 5 or 10 units, for instance. In the mekkablue scripts you will find a Metrics > Delete Small Kerning Pairs that will help you with this task.

Needless to say, do this only with a copy of your font.

Mark attachment:

Consider a Remove Glyphs parameter for deleting combining accents—of course only if your font uses scripts that do not depend on them, e.g., Latin, Greek or Cyrillic. The lack of combining accents will prevent Glyphs from building the mark (Mark Attachment) and mkmk (Mark-to-Mark Attachment) features and therefore reduce the size of your GPOS table. You can achieve that by removing all *comb glyphs.

Be careful though, it may backfire: TT-based files may become larger because they cannot employ the combining accents as components in your diacritics anymore. So, always test, compare and verify. If the file size grows, instead of deleting the combining accents, consider a Remove Features parameter with:

mark
mkmk

CFF-based fonts should always slim down when you get rid of combining marks, because they do not use components in the first place.

More compression:

For CFF-based WOFF and WOFF2 fonts, you can also try disabling subroutinisation. The compression used by WOFF and WOFF2 sometimes actually does work better. It is worth a try, so add the parameter Disable Subroutines to your instance, flick on its checkbox, then export and measure file size.

Testing

According to Miguel Sousa from Adobe, a font that is not tested is a broken font, and he is right. But how do you test a webfont? In browsers of course: Safari, Chrome and Firefox on the Mac, and in Chrome, Edge, and Firefox on Windows. And how do we do that, ‘test in browsers’? Well you have several options.

First of all, right after export, you can run Test > Webfont Test HTML from the mekkablue scripts, available through Window > Plugin Manager > Scripts. It will create an HTML file for the current file (.glyphs or .glyphsproject) inside the mostrecent folder into which you exported a webfont. And it will open that HTML for you straight away in your default browser. Then you can activate OT features, type your test text, and see your font in several sizes. It also provides sample CSS code.

Or you can drag your finished WOFFs into Viktor and Clemens Nübel’s fantastic FontDrop, which they developed for Monotype. Drag your WOFF in, get an overview of your complete font. Good for testing font info, hinting (with waterfalls) and glyph set. Heck, it even provides spacing indicators! Downside: it does not support WOFF2 yet.

Similar to this, you may want to use Roel Nieskens’ genius Wakamai Fondue test page. It is insanely great for testing OT features, and even provides sample HTML and CSS code for your copy-pasting pleasure.

And then there is the great Font Goggles app by Just van Rossum. It supports all kinds of font formats, including WOFF and WOFF2.

Simon Cozens’ Crowbar online tool for debugging shaping/layout issues supports webfonts too. Crowbar uses Harfbuzz to shape the text, and you can precisely see what happens during various stages of OT feature application.


Update 2019-07-30: corrected typos. (Thanks Nathalie.)
Update 2020-09-22: updated for Glyphs 3.
Update 2020-11-13: updated for Glyphs 3, added Font Goggles and Crowbar.
Update 2020-12-04: minor formatting changes, updates, fixed typos.
Update 2022-17-08: minor formatting changes.