Font events: Controlling the flash of unstyled text

This is our second post in an ongoing series about using font events for better control over how web fonts load. Read the first post for an overview of font events, the third post to learn how to control fallback fonts and styles, and the fourth post to learn about JavaScript callbacks with font events.

Screenshot of before and after fonts have loaded on the blog A Working Library
An example of FOUT—before and after fonts have loaded—on the blog A Working Library.

We’ve designed Typekit to deliver fonts to web pages as quickly and efficiently as possible. We strive to minimize download size, use as few requests as possible, and distribute fonts around the globe using a CDN so there’s always a server nearby. We also cache fonts so that subsequent page loads have web fonts available immediately. However, despite our best efforts, there may occasionally be users for whom fonts load more slowly.

In these cases, Typekit users are most often concerned about their visitors seeing an effect commonly know as the FOUT, or the flash of unstyled text. You may have noticed the FOUT before: it’s that brief flash of text in a default font before the web fonts have finished loading.

In fact, whether or not you see any FOUT when using web fonts differs based on which browser you’re using. Thanks to research from Steve Souders, Paul Irish, and others, the differences in how browsers load web fonts have been carefully characterized. Here’s what happens when a web page with Typekit loads in each major browser:

  • Internet Explorer: Nothing is rendered until the web fonts have finished loading. You shouldn’t see any FOUT.
  • Chrome / Safari (WebKit): Text set in a web font isn’t rendered until that web font has finished loading. You shouldn’t see any FOUT.
  • Firefox: Text set in a web font is rendered using the fallback font until that web font has finished loading. You may notice FOUT depending on your connection speed.

So when we talk about controlling FOUT, Firefox is the browser that we’re concerned with. Firefox may decide to change in the future to hide text until web fonts have loaded (like WebKit-based browsers). But thanks to Typekit’s font events, we can make Firefox behave just like WebKit browsers today.

Using font events, we can add CSS styles to hide text that uses web fonts until after they’ve loaded, eliminating the FOUT. This makes Firefox mimic the rendering behavior of Chrome and Safari. However, we also want to make sure that we leave text visible for users that can’t load web fonts due to an older browser, user preference, or disabled JavaScript. This allows our websites to degrade gracefully so that everyone can still see the content, regardless of the style.

Let’s say that I have a blog, and I’m using Typekit fonts for my blog title (which has a class of blog-title) and post titles (which have a class of post-title). Using CSS and font events, I want to hide the blog title and post titles in all browsers (including Firefox) until the fonts have finished loading. Assuming that I already created a kit and have assigned web fonts to the .post-title and .blog-title selectors, here’s what I would add at the end of my blog’s <head>:

<script type="text/javascript" src="http://use.typekit.com/xxxxxxx.js"></script>
<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
<style type="text/css">
  .wf-loading .blog-title,
  .wf-loading .post-title {
    /* Hide the blog title and post titles while web fonts are loading */
    visibility: hidden;
  }
</style>

While fonts are loading, the Typekit JavaScript adds the wf-loading class to the <html> tag. This CSS uses that class to hide the blog and post titles. Once web fonts are detected as active (or inactive), the wf-loading class is removed and the titles become visible again. For users who have JavaScript disabled, the wf-loading class is never applied in the first place, so the titles always remain visible.

By taking advantage of font events in our CSS, Firefox will load web fonts just like WebKit-based browsers such as Chrome and Safari, and we ensure that users won’t see an unsightly flash of unstyled content.

In the next installment of our font event series, I’ll talk about how to maintain control over the appearance of your website for users that can’t load web fonts at all. We’ll use CSS and font events to style appropriate fallback fonts so that the page gracefully degrades, maintaining readability, layout, and even consistency in style. See you next time!

21 Responses

  1. Jason says:

    Hey guys, thanks for the write up.

    Is it the `wf-inactive` class or the `wf-loading` class that gets applied to the element?

    1. Mandy Brown says:

      Use wf-loading to control the FOUT (which shows a fallback font when the web font is loading). The next post will discuss using wf-inactive to control fallbacks for when the web font *can’t* load (because, say, the user is on a really old browser, or a mobile device that doesn’t support @font-face).

    2. Jason says:

      Thanks — I was really asking because it looks like a typo in first para after the code block, when the article mentions the wf-inactive class. Maybe I’m reading it wrong?

    3. Rafal says:

      The same thing here, it isn’t stated in the article where wf-loading class is added. Is this as well?

    4. Rafal says:

      Sorry, I wrote “Is this html as well?” but html in brackets was eaten by the comment parser :)

    5. Mandy Brown says:

      Sorry! Typo fixed.

  2. Ryan Thrash says:

    We’re working on a major relaunch of our website and this was one of the blockers. Thank you!

    Note that will probably help some folks using html5boilerplate or modernizr.js: it’s best to grab the latest 1.6 version of Modernizr and to make sure you put the call to modernizr AFTER both the in-header CSS and Typekit JS because modernizr also adds classes to the body tag.

    1. Bryan Levay says:

      Thanks so much for the tip about Modernizr. It fixed a the problem for a few projects of mine!

  3. Great write-up! The FOUT is the exact reason one client chose to have Typekit fonts removed. :(

    @Ryan: Thanks for the Boilerplate and Modernizr note. I’m using them, but still need some JS explanations.

  4. Jason says:

    Another note: A noticeably nasty FOUT will remain if you follow YSlow or Google Page Speed advice and move the Typekit JS to the bottom of your HTML. Personally, I’m ok with the performance hit on load speed by moving it to the head, because I *want* it to hold off on loading until the fonts are ready!

  5. Max says:

    Great news. The FOUT has kept me from using TypeKit on any productions sites. Thanks for solving this.

  6. Adrian Schmidt says:

    With all the work going into non-blocking JS, isn’t this a step backwards? Is blocking web-fonts really a good idea?

    1. Sean McBride says:

      It’s one more tool in the web developer’s toolbox, but it’s up to you to design what you want the loading experience of your page to be. Some developers prefer to show content as soon as possible, even if the resources to style the content correctly aren’t yet available. Others would rather wait a short time to show the content once it can be styled correctly.

  7. Anders Ringqvist says:

    So if I understand TypeKit´s point of view correct: It´s better to not see any content at all for a while rather than see (and be able to read) unstyled content for a while? How do you handle potential ‘@font-face service outage’?

    1. Jason says:

      Speaking as a Typekit user, I think calling it “a while” may be misleading. This is a very brief < 1 second flash. In that context, going from no text to styled text might be less distracting because users' eyes might not even notice the brief millisecond of load time. Alternatively, loading the fallback font and then switching over to the Typekit font draws a lot more attention to that millisecond.

      Ultimately, it's up to you to use the font events as you want.

    2. Sean McBride says:

      Jason said it: “It’s up to you to use the font events as you want”. If you prefer the Firefox-style “first render in fallbacks, then in webfonts” behavior for loading your site, you can achieve that effect in all browsers using font events as well. Just apply the Typekit font-family names only on .wf-active. For example:

      .blog-title {
      font-family: Arial, sans-serif;
      }

      .wf-active .blog-title {
      font-family: “museo-sans-1″, “museo-sans-2″, Arial, sans-serif;
      }

      The point is that font events give you control over how web fonts load in all browsers. You can do nothing and go with the each browser’s default behavior or use font events to achieve a particular behavior in all browsers. I wrote from the perspective of matching the WebKit behavior since many web developers seem to prefer that (as long as the fonts load quickly). Typekit’s JavaScript has a timeout that ensures that people won’t see hidden text for too long.

    3. Anders Ringqvist says:

      Ok, that´s great, thanks.

  8. Rafal says:

    Thanks, I now have only a short, acceptable delay in Firefox, but a 3 seconds delay in font display in Safari, which—correct me if I am wrong—does not need this delay at all.

    Couldn’t this target problem browsers (i.e. Firefox) only?

    1. Mandy Brown says:

      Rafal, could you share your URL with support@typekit.com? We can take a look. Using the .wf-loading classes should not affect Safari’s behavior.

    2. Rafal says:

      Sura Mandy, email sent, hope it helps.

  9. Noah Read says:

    Thanks so much for this article. I used it on a site I am currently preparing and it worked like a charm.

Comments are closed.