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.

Tags: , , , , , , ,

17 Responses to “Optimizing @font-face For Performance”

  1. base64 encoding adds 33% overhead for the encoding, so I’m not sure turning large files into a data: URI is what I’d call a optimization!

  2. malte says:

    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.

  3. Robert says:

    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.

  4. Da Scritch says:

    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 😉

  5. Well, a 10-15% overhead for a regular serif, bold serif, italic serif, nevermind a whole sans-serif family…it all adds up!

  6. Robert says:

    @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.

  7. Mithgol the Webmaster says:

    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.

  8. Pepe says:

    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

  9. charles says:

    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?

  10. @Robert Quite right, that’s one of the reasons I’m happy FF3.5 shows you the text in non-@font-face fonts first.

    Also, Typekit is supposed to break up the font files in different bits (as part of their drm font-protection) which would add extra latency…

  11. […] Optimizing @font-face for performance […]

  12. […] how I could dynamically add a dropped font to be used in the page. I saw this article on embedding custom fonts using a base64 encoded string. In the file API we have the getAsDataURL() method to return a file as a data url […]

  13. Luke Rotherfield says:

    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 🙂

  14. […] fonts with data URIs is the same as embedding images, except with a different MIME […]

  15. […] in the example above are images. In some ways using @font-face makes sense but not so sure the filesize is always going to work in its favor. Also, some browsers don’t handle moving and scaling text all that […]

  16. […] fonts with data URIs is the same as embedding images, except with a different MIME […]

  17. Use base64 encoded font and then serve @font-face .otf files to IE only using comments. This avoids the Flash Of Un-styled Text issues and is extremely fast.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

By submitting a comment here you grant this site a perpetual license to reproduce your words and name/web site in attribution.