Wrestling With WebFonts In Firefox

W

eb fonts are pretty hot topic as of late. With the up rise of CSS3, people are trying to do more with pure HTML & CSS rather than relying on images to accomplish similar task. Logos, banners and things of the sort tend to be the most popular use cases, but it isn't uncommon to see custom fonts used throughout an entire site.

Although it is a more recent craze, support for web fonts has been around for a long time. You could render custom fonts in browsers as early as Netscape 4 Internet Explorer 4. As is usually the case with many things in the css realm, the problem with fonts has always been differences in browser implementation. Each browser supports a different font file format. Opera Webkit browsers tend to like TrueType fonts. Internet Explorer supports Embedded OpenType fonts, as does Firefox. This contributes to the nastiness that is the fallback hell we lovingly call CSS. Luckily, there are services available today such as Typekit, and FontSquirrel.

Using Web Fonts

Declaring fonts is surprisingly easy to do. Once you have your font file somewhere on the file system they will be served from, its a matter of defining a new font family. I personally like putting assets that will be used be style sheets in a sub directory of the style sheets them selves, so I don't have to worry about folder locations and having nasty ../../ all over the place - everything just kind of works out:

@font-face {
  font-family: 'MyFont';
  src: url('fonts/MyFont.eot');
  src: local('☺'), url('fonts/MyFont.woff') format('woff'),
  url('fonts/MyFont.ttf') format('truetype'),
  url('fonts/MyFont.svg#webfonthWQiC2Xj') format('svg');
  font-weight: normal;
  font-style: normal;
}

And that's all there is to declaring a font. Now you can use it in your style sheets like any other font.

.myfont{
  font-family: "MyFont", Helvetica, Arial, sans-serif;
  font-size: 1em;
  font-weight: normal;
  color: rgb(00, 00, 00)
}

You can use that css class like any other and you magically have custom fonts with fallback all the way back to Netscape Navigator 4! But wait, there is a problem. Of course there is a problem, nothing that awesome on the internet comes without a giant face-palm

The Problem

So what is the problem? I'll tell you want the problem is - Stupid Firefox! That's the problem! When you open up Firefox, there is a pretty good chance that either:

  • The request for the fonts is aborted by firefox
  • The font renders as a default font

WTF, Firefox? WTF? If this has happened to you, it probably comes down to an obviously simple oversight on your part. In most situations your css is being served from a different domain or sub domain than your site. Firefox seems to be the one browser that does allow Cross Domain Requests for font Files. For example, in my case, my site is served from www.codedependant.net, where as my static files ( js, css, images, etc ) are served from media.codedependant.net.

In all other cases, this works out just fine. But in the case of fonts, Firefox stops the request, mainly to protect the licensing of the font, so as people who do not have a license for a font can't just link to it and steal it. Fine. Firefox - 1 , Eric - 0.

Solutions

Not to worry, there are a couple of things that we can do to get around this. If you are serving font files from an Apache web server he first thing you can try is to add a .htaccess file to the directory where the fonts are being served from to set the Acess-Control-Allow-Orgin header on the requests for the files.

<FilesMatch "\.(ttf|otf|eot|woff)$">
  <IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
  </IfModule>
</FilesMatch>

However, if you are like me and use Nginx, this isn't going to help, as Nginx doesn't use .htaccess files. At this point, much like myself, you are probably ready to say:

F*%K IT! Just use comic sans, and call it a day

Hold on a minute, we are a not with out means for God's sake! Base64 encoding to the rescue. That's right, we can Base64 encode the font files and embed them into the style sheet, which will never be subject to an additional HTTP request or Cross Domain Hoo-Haw from FireFox. And it would look something like this:

@font-face {
    font-family: 'MyFont';
    src: url('MyFont.eot');
}
@font-face {
    font-family: 'MyFont';
    src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAGgg...) format('woff'),
    url(data:font/truetype;charset=utf-8;base64,AAEAAAATAQAABAA...) format('truetype'),
    url('myriadpe-webfont.svg#MyriadProRegular') format('svg');
    font-weight: normal;
    font-style: normal;}

You don't need to encode the .eot files for Internet Explorer, as IE doesn't adhere to the same Cross Domain policy for fonts as Firefox does and IE is the only browser that uses the .eot format. From there all of the CSS fallback rules behave as expected.

While the method of Base64 encoding a font set will contribute to a larger file size in your style sheets, it reduces the number of requests sent out to fetch additional files. In general, it is typically more efficient to pull a single larger file over the wire rather than multiple smaller request. Usually be cause browsers have a limit on the number of concurrent requests at a given time.

So, in a nut shell, that is all there is to web fonts. Another example of old technology being reborn as "new". While, admittedly, a bit more work and fumbling around than it should have been, it isn't all too difficult to get it working in a wide variety versions of browsers in the wild.

firefox webfonts css3 base64