Speeding up your Webfonts

Mathias Biilmann

The era of the font-face is upon us! During the last couple of years the growing support across platform for custom web-fonts via the CSS @font-face rule has completely changed the game for typography on the web.

While there's a bit of trickery to generating a Bulletproof @font-face Syntax the basic idea is simple to grasp: the @font-face rule allow us to import a font file from a URL and use that font in our CSS.

This is great, but as with seemingly all things web, there's still some trickery to it.

Speed me up, Scotty!

The biggest pain-point of web-fonts, is having to wait for them to show up. When a page design depends on fonts referenced via @font-face, none of the text set in those fonts can be displayed before the actual font-file has been loaded by the browser.

Because of this you'll always want to make sure that your font-face files have all the proper HTTP caching headers set and whenever possible you'll want to serve them out of a dedicated Content Delivery Network (CDN).

For those in the dark: a CDN provider has a network of servers in data-centers all over the world. When a request to a resource hosted on the CDN comes in, the server closests to the user will serve out the response and keep it cached for further request. Ideally most people will get a file hosted on a CDN directly from the cache on an edge-server very close to them. This can cut down latency and file-transfer times immensely.

Bad URI or cross-site access not allowed

You might think serving out you @font-face fonts from a CDN is as simple as just uploading them to your CDN of choice and then pointing the src attribute to your CDN URL, but you would be wrong.

Historically the @font-face rule has been controversial because using a remote font as part of a Web page allows the font to be freely downloaded. This could result in fonts being used against the terms of their license or illegally spread through the Web.

Browser vendors have gone through some troubles to at least put in place some protections to disallow people from abusing this. The main one is based on the Origin and Access-Control-Allow-Origin HTTP headers.

When FireFox requests an external font-face file (ie. one that's not hosted on the same domain as your web site) it will send the base url of the website (eg. http://www.webpop.com) in the "Origin" header of the HTTP request. Unless the response from the server includes an "Access-Control-Allow-Origin" header matching the domain of the Origin header, FireFox will throw a "Downloadable font: download failed" security exception and refuse to make use of the font-face.

Cloudfiles and Access-Control-Allow-Origin

This limitation can get in the way when you try to serve a font file out of a CDN, since the font URL will always be different than your site's base URL. To get the font to work in all browsers, you'll need to set the right Access-Control-Allow-Origin header.

At Webpop we use Akamai as a CDN, by uploading files to a public container in Rackspace's Cloudfiles.

It's worth noting that for any Webpop site, our system will automatically handle all the trickery of setting just the right headers for your font files, but here's how you can do this for a non-webpop site:

When setting CORS headers (like Access-Control-Allow-Origin) for a CloudFiles object, you can either use the CloudFiles control panel, or do it programmatically via the CloudFiles API.

The Rackspace documentation currently states that the only way to set these headers are via the API, but don't let that deter you, it's on the secret menu. Navigate to your container, upload the font file, then click the little gear and pick "Edit Headers...". You can add the right header in the resulting dialog.

In our case we do everything through the API. For that we use the Cloudfiles Ruby gem. Here's a complete example of uploading a font file for use on http://www.webpop.com to CloudFiles from IRB:

require 'cloudfiles'

connection = CloudFiles::Connection.new(:username => "your-username", :api_key => "your-api-key")
container = connection.container("your-cloudfiles-container")
File.open "/path/to/font-face-file.woff" do |file|
container.create_object("your-object-path.woff").write(file, {
'Access-Control-Allow-Origin' => "http://www.webpop.com",
'Content-Type' => "application/font-woff"

HTTPS, Wildcards and Licensing Issues

The Origin is a fully qualified url like http://www.webpop.com and not just a domain name. This can cause problems if your site works both under HTTP and HTTPS, since the browser will treat those as two different origins.

There's two ways to get around this, each of them with their own problems.

The first one is to set a wildcard Origin. When you set Access-Control-Allow-Origin to "*" you tell the browsers that any origin is allowed and basically lift all restrictions on serving the font.

Note, that while this works fine with Rackspace's Cloudfiles and Akamai, it can cause issues with caching on other CDNs such as Amazon's Cloudfront.

For most non-free fonts this will also be against the font license, since you're basically setting up a public version of the font-face that anybody can use on any website without limitations. So be careful before choosing this option.

The other way to solve the HTTP/HTTPS issue is to upload two different versions of the font-face, one for HTTP and one for HTTPS and give each of them their own Access-Control-Allow-Origin. This obviously works, but now you need to make sure to use the right value for the src property in your CSS depending on whether people are viewing the HTTP or the HTTPS version of your site. If you've pushed your CSS to a CDN as well, you'll need two different CSS files for HTTP and HTTPS as well, and then make sure to link to the right one based on the protocol.

Let's just pop:bundle it!

As you've no doubt seen there's more than meets the eye to managing your own webfonts. I hope this article will be useful for those of you who need to do it themselves. If you're using Webpop: don't worry about any of it!

Our <pop:bundle> tag will automatically push any font-file referenced in your @font-face straight to Akamai and set the right Access-Control-Allow-Origin header. It'll also bundle all your CSS files and serve them out of Akamai as well. If you're using HTTP we'll automatically link the right css/font-files depending on the protocol and make sure your visitors get the best experience possible while you get to usher in the new era of web typography.

« Back to Blog Index

Sign up now

30 days free trial. Sign up in 60 seconds. Upgrade, downgrade, cancel at any time.
blog comments powered by Disqus