Mozilla Web Development

Optimizing @font-face For Performance

You want to use @font-face, then you realize it’s got some downsides. First of all, it’s another HTTP request, and we know that the golden rule of web performance is to keep HTTP requests to a minimum. Secondly fonts aren’t even small files, they can be 50k+ in size. Lastly the lag of fonts loading last means you page seems to morph into it’s final form.

Here’s a cool little optimization. By using a data: URL you can use the font inline by encoding in base64. For example:

@font-face {
    font-family: "My Font";
    src: URL("data:font/opentype;base64,[base-encoded font here]");
body {
    font-family: "My Font", serif

You can see this in action here. This seems to work fine in Firefox 3.5, and Safari 4 (presumably any modern WebKit based browser). Other browsers will simply act as if they don’t support @font-face.

In practice I’d recommend putting it in a separate stylesheet rather than inline CSS so that your pages are smaller and CSS can be cached for subsequent page views.

Data URL’s are part of Acid2, which most modern browsers either pass or plan to pass. If you use an Open Type font you’d get pretty decent compatibility (IE only supports Open Type). Using True Type you’d still get pretty good compatibility sans IE. Check the @font-face page on MDC for more details. Unlike images, browsers that support @font-face are likely to support data: URL’s as well, making this a pretty good solution.

Special thanks to Open Font Library for having some nice free fonts with awesome licensing. This post was partially in response to a comment left the other day on my @font-face hacks blog post.

17 replies on “Optimizing @font-face For Performance”

The base64 encoding used in the data: URI will increase the font’s size by a third. Gzipping the CSS file probably reduces this to something lower, but not to a factor of one. So if file size matters, it’s probably better to leave the font a separate file. After the first page load, (in a proper setup) it will be cached just like the CSS.

Also, the whole page won’t be shown until *all* CSS files have downloaded completely. So while this technique prevents some text from showing up in a “wrong” font for a short while, it prevents the whole page from showing up at all for that same time.

Very true.. but most sites gzip these days cutting down the file size… I suspect you’d see 10-15% overhead in practice.

Considering the large amounts of JS and images on many sites today and the proliferation of broadband connections, file size is generally less important than the # of requests.

A typical cable modem connection these days can easily handle 6Mbps and burst as high as 20Mbps. Unfortunately the latency is still there.

An extra 30kb (assuming 2x 15kb overhead on a base64’d 50kb font) is going to be perceived faster in many cases than an 2 extra requests (assuming you only use 1 serif and 1 sans serif font). Especially if your not offloading to a CDN or other low latency origin.

This “good advice? will be spotted by copyright-fanatics to enweighten their websites in 3…. 2…. 1….
Oooooooh ! JPEG headers and backgrounds urldata-encoded in the source code !

Just joking. Anyway, it is very useful, if you use this kind of technique (and it’s better for very small documents, as 1Kb PNG images, not for 50Kb fonts), to activate gzip compression on server-side. But remember that CSS and JS zipped-served are NOT cached by MS-W-IE. So, use it a lot, it makes a better “cool and fast attitude? for non Trident based modern navigators 😉

@James John Malcolm: Yes, but in practice the latency of several fonts will likely be more of a performance barrier than a few extra KB.

A separate stylesheet is no better than a separate font file.

In fact, if both are external, I won’t bet (without pre-testing) on whether the Access Control headers fail for the former.

Are fonts really cashed? I still get the effect of seing the text shown for a milisecond without the downloaded font when refreshing a page that downloads a font.

This effect is quite ugly, I don’t see this with Safari 4

But, if you could use localStorage that is new in FF3.5 then the font would ONLY be downloaded 1 time.
The only catch is how to get the data:URL string from localStorage and into @font-face src?

Great little article thanks, I used it on my site just now and no-longer get the whole site in serif then a split second later turning into nice font, just loads straight into museo 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *