Web Font Anti-Patterns: Inlining

Oc­to­ber 13, 2015

A very com­mon anti-pat­tern is in­lin­ing font files in a stylesheet us­ing base64 en­cod­ing. In­lin­ing fonts avoids the over­head of an HTTP re­quest, but that ad­van­tage may not out­weigh the many down­sides.

In­lin­ing is ben­e­fi­cial when you load mul­ti­ple fonts. Nor­mally a browser needs to cre­ate a new con­nec­tion for each re­source. It takes a cer­tain amount of time to cre­ate a con­nec­tion and this cost adds up. When all fonts are com­bined in the same stylesheet you only need to pay for the con­nec­tion over­head once. This may seem very at­trac­tive, but there are some se­ri­ous dis­ad­van­tages to in­lin­ing.

These dis­ad­van­tages be­come vis­i­ble when you com­pare a net­work time­line of nor­mal font load­ing with a net­work time­line of in­lined fonts. Be­low is a net­work time­line of the de­fault font load­ing be­hav­iour. The fonts are down­loaded in par­al­lel and ren­der as soon as they fin­ish; font a is ren­dered first, fol­lowed by font b, and fi­nally font c. This is pro­gres­sive ren­der­ing. Fonts are ren­dered as soon as they fin­ish down­load­ing.

Browser timeline downloading three fonts in parallel.

Here is what the time­line looks like when you in­line those three fonts in the same stylesheet. In­stead of down­load­ing the files in par­al­lel the browser only down­loads a sin­gle CSS file. This sin­gle file is much larger be­cause it con­tains all three fonts, and takes longer to load than three sep­a­rate font files down­loaded in par­al­lel.

Browser timeline downloading three fonts inlined in CSS.

This by it­self is al­ready in­ef­fi­cient be­cause browsers can down­load more than one re­source at a time (in fact, many browsers al­low up to six con­nec­tions per host). If you in­line fonts you’ll miss out on the ben­e­fits of par­al­lel down­loads, pro­gres­sive ren­der­ing, and lazy load­ing.

When you com­bine all the fonts on your page in a sin­gle stylesheet they will all load at the same time: when the stylesheet fin­ishes load­ing. The browser will nor­mally lazy load fonts by only down­load­ing them if they are used. By in­lin­ing all fonts in a stylesheet all of them will be down­loaded, even if some are not used on the page.

All of these is­sues af­fect web font per­for­mance neg­a­tively. Re­mem­ber that fonts should be down­loaded with the high­est pri­or­ity and as soon as pos­si­ble be­cause they block ren­der­ing. In­lin­ing will se­verely im­pact the ac­tual and per­ceived per­for­mance of your site.

Base64 encoding and decoding

The base64 en­cod­ing and de­cod­ing also comes at a cost. A base64 en­coded file is roughly 30% larger than its bi­nary form. You could negate most of this by us­ing GZIP com­pres­sion, but the re­sult­ing file size will still be slightly larger. Base64 de­cod­ing does­n’t come for free ei­ther. Fonts em­bed­ded in a stylesheet us­ing base64 en­cod­ing will need to be de­coded be­fore they can be parsed. This cost is in­signif­i­cant on most desk­top com­put­ers, but can be prob­lem­atic on de­vices with less pow­er­ful proces­sors such as tablets and mo­bile phones.

Av­er­age WOFF file size out of a 20.000 font file cor­pus. Base64 en­cod­ing the WOFF file in­creases the file size by about 30%, but GZIP com­pres­sion re­duces this to close to the orig­i­nal file size.

Font format negotiation

An­other big prob­lem with in­lin­ing is that it lim­its you to a sin­gle web font for­mat. Be­cause the en­tire font file is in­lined in CSS, adding sup­port for an­other font for­mat in­creases the size of the CSS file (es­sen­tially you would be stor­ing and trans­mit­ting the same font once per for­mat). You could work around this by try­ing to guess the web font for­mat sup­port based on the browser’s user agent string, but this is a rab­bit hole you don’t want to go down into. (Be­lieve me. I’ve been there — it’s not a happy place.)

If you don’t want to do user agent sniff­ing you’re left with serv­ing the font for­mat with the widest browser sup­port: WOFF. That’s per­haps suf­fi­cient for most web­sites, but you’ll miss out on the ben­e­fits of newer for­mats that of­fer much bet­ter com­pres­sion rates, such as WOFF2.

Caching

Fi­nally, in­lin­ing also neg­a­tively af­fects caching. If you up­date one (or mul­ti­ple) fonts in your stylesheet you’ll need to in­val­i­date the browser cache for the en­tire stylesheet (for ex­am­ple, by chang­ing the name of the stylesheet). Your vis­i­tors will need to re-down­load the CSS file con­tain­ing all the fonts even though most of them did not change. If the font files were served (and cached) as in­di­vid­ual files only the up­dated font file would need to be down­loaded again, and the re­main­ing files can stay cached.

Closing thoughts

So, to sum up: un­less you’re load­ing a lot of fonts (let’s say more than 10) in­lin­ing is a bad idea. It’ll af­fect your ac­tual and per­ceived per­for­mance, thereby mak­ing your site load slower. It also dis­ables font for­mat ne­go­ti­a­tion, pro­gres­sive ren­der­ing, par­al­lel down­load­ing, and lazy load­ing.

With the in­tro­duc­tion of HTTP/2, in­lin­ing is an even less at­trac­tive op­tion. HTTP/2 en­ables par­al­lel down­loads over the same con­nec­tion. This has the same ben­e­fit as in­lin­ing (avoid­ing con­nec­tion over­head) but none of the down­sides. Caching, font for­mat ne­go­ti­a­tion, lazy load­ing, and pro­gres­sive ren­der­ing will con­tinue to work as ex­pected with HTTP/2. Many browsers, servers, and host­ing providers al­ready sup­port HTTP/​2, so you can start us­ing it to­day in­stead of in­lin­ing!

This ar­ti­cle is part one of an on­go­ing se­ries on web font anti-pat­terns. Read the in­tro­duc­tion, part 1, part 2, part 3, and part 4.