- The Dark Side of Web Fonts
- Further Reading
We’ve given websites a lot of crap over the year for such things as
In many cases, the excuses pile up, and some challenges seem more insurmountable than others. Publishers need a revenue model, people need to know who’s visiting the website and reading the article, and non-technical editors need to build some website at one point, and might be afraid of stepping into the minefield of an outsourced code base.
But then there’s this:
That right here is seconds of staring of absolutely nothing on a website, because someone decided they wanted non-standard fonts, either because you had to pry them from the cold dead hands of the webdesigner, or because the typeface was considered important for #branding. (People generally don’t talk about the #branding of a website that loads execrably.)
What you see is the so-called Flash of Invisible Text (FOIT).
Most websites have this problem—it is a very common experience, because most people have got it in their head that they need to use fancy web fonts for their website.
The good news is that it’s easy to fix.
The bad news is that this means you don’t have a lot of excuses for not fixing it.
Given that the target demographic was largely Indian, my concept was informed by optimization as the main priority.
I was largely successful in this, and one of the accomplishments—amongst others, detailed in the GitHub issue—was bringing the size of the entire page below 100 kB.
When a project gets that small, everything starts to stand out. It caught my attention that my Raleway fonts took up more than two thirds of the entire page, which felt ridiculous to me.
I’ve grown very fond of custom web fonts, since I started using the Skeleton CSS framework, which powers the majority of this site, and many others as well.
The Dark Side of Web Fonts
But being obsessed with optimization, I always have to justify the use of it to myself. And for a project aimed at a country with varying speeds of bandwidth—compounded by the fact that one the world’s biggest CDNs only just opened data centres in a country of 1.25 billion people1 after we began on the project—playing fast and loose with fancy fonts demanded a justification.
Because two really bad things happen when you use a custom web font:
- Loading the font delays (blocks) the loading of the rest of the website (DOM).2
- Your browser renders the website, regardless of whether the font has finished loading, which creates a Flash Of Invisible Text (FOIT).
This is preventable, if developers want to do something about it. What follows is a description of how I improved the loading of web fonts on Goal Tracker, and what the results were. I’ll skip to the results first, so I don’t lose you with the boring code samples.
Your mileage may vary, but testing on a slow-ish 3G connection, I got the following results:
Here they are as animated GIFs; you have to click them first, though.
Here are the main takeaways from the improvement:
- The website first renders (ie DOM finished)
- in 2.5s on the unoptimized version
- in 1.3s on the optimized version
- The website is readable
- in 3.5s on the unoptimized version
- in 1.3s on the optimized version—with fallback fonts
- in 2.3s on the optimized version—with the web fonts
Again, this is for a web page with a minimal size footprint, so make of it what you will. If you can shave off a second for a website to render and two seconds for it to be readable even on a web page smaller than 100 kB, then any website will benefit.
The only “downside” is that users will see a Flash Of Unstyled Text (FOUT), a smaller—and briefer—inconvenience compared to a FOIT.
The following how-to is from my personal HTML guide for web fonts. I have abridged the code snippets from the guide to make them more readable. Some asides also wound up on the cutting-room floor.
Change your stylesheet from including the custom font that looks like so:
At the bottom of the HTML body, add the following using Font Face Observer:
This defeats FOIT by loading the fallback fonts first and then applying the custom fonts, once, and only once, they’ve finished downloading.
Deferred Font Loading
Either retrieve web fonts from Google Fonts:
Or load them locally using localfont.com.
fonts.css looks something like this:
Deferred Font Loading
- This method does not work in Android < 4.4 because the onload handler does not fire when content is available—I’m looking into a workaround for this.
- Some browsers appear to still block CSS render despite
media="none". This means CSS loads as it usually does—I’m looking into this.
Keith Clark: “Loading CSS without Blocking Render”
Deferred Font Rendering (FOIT)
FontFaceObserver has been tested and works on the following browsers:
- Chrome (desktop & Android)
- Safari (desktop & iOS)
- Android WebKit
You could say that this might not work on literally every browser, with the worst case scenario being that the page just loads as it normally would. You would also have to compare this browser compatibility list with the tech stack you’re currently using, which is probably not all-inclusive either.