Paul Irish

Making the www great

Chrome and @font-face: It’s Here!

January 25, 2010: It is now in the stable Chrome release! The wait is over, everyone. :) [release notes]

Today, Zeldman issued an ultimatum that we’ve all been feeling recently:

It’s true, every major browser supports @font-face:

  • Internet Explorer: since IE5
  • Firefox: since FF3.5
  • Safari: since Safari 3.2
  • Opera: since Opera 10

But.. Google Chrome currently does not enable @font-face linking to ttf and otf.

It actually does support SVG fonts in a @font-face declaration. View this demo in Chrome or Chromium to see svg fonts in action. Divya has some great research around fonts and SVG if you’re interested in more.

You can turn it on, at will

You can enable web fonts with an executable switch: −−enable-remote-fonts.

On Windows, you can tweak the shortcut path, like so. With Chromium on OS X, you use Terminal to launch:

1
/Applications/Chromium.app/Contents/MacOS/Chromium --enable-remote-fonts

With proper Google Chrome on OS X, you need to escape the spaces:

1
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --enable-remote-fonts

With Chromium on Linux[1]:

1
chromium-browser --enable-plugins --enable-remote-fonts %U

Once you enable it, all @font-face stuff works just as you’d expect, including the bulletproof @font-face syntax [demo] and the Nice Web Type demos.

But we need web fonts working by default

Wait, so why is this wonderful feature disabled by default? Security review. Ian Fette, the program manager of Chrome, indicated that they need to explore how do webfonts in a “reasonably safe manner”. So that’s the holdup. This ticket on the Chromium bug tracker tracks the feature being enabled by default.

Okay, so when do we get our toy? Soon, in fact!

Chrome is my default browser, so my patience on this issue ran dry recently. I emailed Takuya, an engineer at Google Japan, who is working on this and he said:

We are almost done. The code is under review internally within Google. I’m expecting to make it public no later than a week or so.

So I expect we’ll be seeing @font-face support enabled by default in the Chrome dev builds soon. Based on their release schedule I think it’ll be near the end of the year when we see it in Chrome stable. That’s good news; let’s hope we see it sooner.

2009.10.19 : The ticket tracking @font-face on by default gained the Milestone-4 label, indicating it will be included in Chrome 4 Stable.

2009.11.04: The Chromium team has released ots - an OpenType sanitizer library meant to clean any security concerns from a font file included via @font-face. They have also filed a bug upstream with WebKit to integrate this code at the Webkit level. Finally we see the fruit of their security review.

2009.11.18: Remote fonts are now enabled by default!!! This should only be in the dev builds for now. I’ll update when it makes it to beta builds and eventually the stable. But right now it still looks like we’ll see this in version 4 stable. (Nov 21: confirmed its in dev builds.. starting with version 4.0.249.4 [blog post], [rev 32300])

2009.12.09: @font-face support is now in the Chrome Beta of both Windows and Mac.

2010.01.25: @font-face support is now in the Windows Chrome Stable release! [release notes]

Avoiding the FOUC v3.0

FOUC is an unwelcome guest to your soirée of intertube funtimes. He comes in and distracts users eyes with things they shouldn’t be seeing, and then departs ever so quickly. We don’t like him.

So you’ve likely seen code like this:

1
2
<body>
  <script>document.body.className += 'js';</script>

No good. Scripts in the body block rendering so we can do better[1]:

1
2
<head>
  <script>document.documentElement.className += 'js';</script>

Here we’ll be adding the class to the HTML element instead of the body, which we have access while we’re in the HEAD. (Naturally CSS works just fine with a html.js selector, though this doesn’t validate in HTML4)

But here’s my big hang-up:

I prefer to write unique css for the no-javascript user. I don’t want to be writing .js in front of every selector for my basic accordion/carousel/etc widgets. It’s terribly tedious. I really just want a .no-js hook.

My solution:

1
2
3
<html class="no-js">
<head>
  <script>(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)</script>

The markup has a no-js class on HTML by default but we’ll very safely change that to ‘js’ inside the head. That compressed line of javascript is basically:

1
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/,'js');

But I make it small as it’s one of the only scripts that should run in your head. Because everyone has their scripts near their </body> tag, right?

We use the same approach in Modernizr, because we want the classes to be all set on the HTML element right when the BODY content starts loading in. Fight the FOUC!