Typekit, slow hosted scripts and the Flash of Unset Text
While working on the forthcoming redesign of the Beam website, FF DIN was made available for licensing with @font-face in WOFF format. It was also released on Typekit.
DIN is Beam’s corporate font and this news presented me with an opportunity to pursue Typekit as an alternative to font replacement techniques like sIFR and Cufón.
While it would appear that the perfect solution had just dropped into my lap; Typekit is a hosted service and this dependance on an external service concerned me.
What if the Typekit service was unavailable?
I started testing the effect of a prolonged delay on the rendering of the page. I created a PHP script that sleeps for 5 seconds and then returns the Typekit loader.
Loading typekit in the HEAD
First I initiated Typekit in the HEAD of the document. This breaks Rule 6 of high performance web sites; but i decided to include it for completeness.
<head>
<script src="http://phil/slow-typekit-loader.php?duration=5"></script>
<script>try{Typekit.load();}catch(e){}</script>
</head>

As I’d expected the page doesn’t render at all until Typekit has responded. This would be a pretty terrible situation.
Loading Typekit at the bottom of the page BODY
Including the SCRIPT at the foot of the page will allow the page to render while we’re still waiting for Typekit to download.
<body>
<script src="http://phil/slow-typekit-loader.php?duration=5"></script>
<script>try{Typekit.load();}catch(e){}</script>
</body>

Much better! The page can render even while we’re still waiting for Typekit. But in that time while we’re waiting for Typekit our text is rendered in default system fonts and only rendered in our web font when it’s finished downloading. This isn’t exactly desirable.
Use a ‘best fit stack’ to soften the shock
In last years 24 ways Mark Boulton wrote ‘Designing for the switch’. In it he suggests specifying a set of system fonts that look similar to our desired web font. This will help us reduce the impact of our flash of unset text.

That’s a good start.
Use some JavaScript and CSS to transition
The Typekit library adds a class of ‘tk-active’ to the page BODY after the fonts are loaded; we’ll use this as a hook for some styling to hide the content of the page until our fonts are available.
.tk-loading{ opacity:0; } .tk-active{ opacity:1; -moz-transition:0.2s opacity ease-in; -webkit-transition:0.2s opacity ease-in; transition:0.2s opacity ease-in; }
<body class="tk-loading"> ... <script src="http://use.typekit.com/KIT_ID.js"></script> <script> try{ Typekit.load(); }catch(e){} </script> </body>
This will hide the contents of our page and show it once Typekit has loaded our fonts. But that brings us back to square one. If Typekit is taking a long time to load our page won't be displayed
.
Add some magic with LABjs
LABjs is a great tool for managing JavaScript execution and dependencies.
The first thing we'll do is switch to using JavaScript to set our loading class. We'll do this so that users with JavaScript disabled won't be affected by our meddling.
<body> <script> document.body.className = 'tk-loading'; </script> ... </body>
Next we'll load Typekit using LABjs.
<body> ... <script> $LAB.script('http://use.typekit.com/KIT_ID.js') .wait(function(){ try{ Typekit.load(); }catch(e){} }); </script> </body>

Another advantage to loading Typekit with LABjs is that we can load other libraries asynchronously and execute them independently. This is great because should Typekit or any other externally loaded script take a while to load it won't block any other scripts.
We'll also add a timeout to our page to add our 'tk-active' class, just in case Typekit takes too long to load (we have to do everything we can to ensure the user isn't stuck with a blank page).
<body> ... <script> setTimeout(function(){ document.body.className = 'tk-active'; }, 1000); </script> </body>
Putting it all together
<!DOCTYPE html> <html> <head> <style> .tk-loading{ opacity:0; } .tk-active{ opacity:1; -moz-transition:0.2s opacity ease-in; -webkit-transition:0.2s opacity ease-in; transition:0.2s opacity ease-in; } </style> </head> <body> <script> document.body.className = 'tk-loading'; </script> ... <script> setTimeout(function(){ document.body.className = 'tk-active'; }, 1000); $LAB.script('http://use.typekit.com/KIT_ID.js') .wait(function(){ try{ Typekit.load(); }catch(e){} }); </script> </body> </html>
Limit the weights and variants
By default a kit will contain all weights and variants of the fonts family. This can make the font download quite large (often in the region of 250KB+). Unchecking the flavours that aren't used can make a massive difference to download times.

Hopefully someone will find this useful. I'm sure i'll be referring back to it the next time I use Typekit.
Make a trackback.
Interesting – is there a way of cancelling the Typekit request once the timeout kicks in? I think I’d rather it not subsequently restyle the text once I’ve given up and displayed it.
@Ciaran, If you used a class to prefix your selectors in the Typekit editor you could just remove that class from your page to prevent the type setting from taking place.
@Carl I guess – there’s still an HTTP request being made in the background that I don’t need any more – hmm.