Solving our FOIT issues with Web Font Loading

Firstly if you’re unaware of what FOIT is then this might not be the article for you, but if you insist on reading along it stands for Flash Of Invisible Text. This flash occurs on a number of websites that use non standard fonts through @font-face in their CSS files and it happens either between the hiding of a default system font and a newly loading font or from the time the website starts to render and the specified fonts appear.

Similarly there is also FOUT which is Flash Of Unstyled Text and this is when a default system font is shown prior to the font the developer has actually specified to show.

Not ideal

Neither instances are fantastic as both make for a jarring user experience. As developers the problem is something of our own making. Mostly browsers used to implement @font-face fonts with FOUT but because the change from one font to another can cause a number of layout shift many developers attempted to hide text while the intended fonts loaded.

The browser vendors followed suit but when fonts can load slowly on mobile connections, and possibly not load at all, a user can be sat looking at a website with no content for far too long; ever increasing the chances they bail out and go elsewhere. So as far as usability goes FOIT is to be avoided.

The Solution

So to solve this problem we’ve begun to implement web font loading through the use of the FontFaceObserver polyfill. What this does is give us far more control over the display of fonts so that on initial load we can make the text visible as soon as the page begins to render and then swap in the correct font only after it’s loaded. There might still be some layout shift on occasions where the new fonts are very different from the fallback but in these cases altering the font size and line heights of the fallback font may help reduce some of that shift.

Here is a view of our site loading before (top) and after (bottom) we added the polyfill. You can see that now as soon as the site start to render the fonts are visible, while before the fonts were very slow in appearing. Unfortunately the thumbnails are too small to show the change from fallback to @font-face fonts.

filmstrip
Before & After

And this is the code we’ve implemented to get there…

 

var roboto300 = new FontFaceObserver('Roboto',{weight: 300});
var roboto400 = new FontFaceObserver('Roboto',{weight: 400});
var roboto500 = new FontFaceObserver('Roboto',{weight: 500});
var roboto300italic = new FontFaceObserver('Roboto',{weight: 300, style: "italic"});
var roboto400italic = new FontFaceObserver('Roboto',{weight: 400, style: "italic"});
var roboto500italic = new FontFaceObserver('Roboto',{weight: 500, style: "italic"});

var montserrat400 = new FontFaceObserver('Montserrat',{weight: 400});
var montserrat700 = new FontFaceObserver('Montserrat',{weight: 700});

Promise.all([
  roboto300.load(),
  roboto400.load(),
  roboto500.load(),
  roboto300italic.load(),
  roboto400italic.load(),
  roboto500italic.load(),
  montserrat400.load(),
  montserrat700.load()
]).then(function () {
  document.documentElement.className += " roboto-loaded montserrat-loaded";
  setCookie('fonts-loaded','true')
});
<? if($_COOKIE['fonts-loaded'] == 'true'){ ?>
  <html lang="en" xml:lang="en" class="no-js roboto-loaded montserrat-loaded">
<? }else{ ?>
	<html lang="en" xml:lang="en" class="no-js">
<? } ?>
$primary-font-family: Roboto, Helvetica, Arial, sans-serif;
%primary-font-family 							{font-family:Arial, Helvetica, sans-serif;
	.roboto-loaded & 								{font-family:$primary-font-family; font-weight:300;}
}

$secondary-font-family: Montserrat, Roboto, Arial, Helvetica, sans-serif;
%secondary-font-family 						{font-family:Arial, Helvetica, sans-serif; font-weight:700;
	.montserrat-loaded & 						{font-family:$secondary-font-family;}
}

So, yes we’re loading possibly a few too many fonts at different weights and styles. And our loading times seem to be a bit all over the shop at the moment making an exact comparison difficult. But these are something to investigate another day.

Issues

While not a complex change, the above wasn’t achieved instantly with the documentation lacking in some areas.

One of the biggest issues we came across was that we were still getting the Flash of Invisible Text. At this point, it came between the fallback font being hidden and the new font being loaded, and lasted arouns 500ms.

While we tested a few different things, which ultimately may have other benefits, the final solution was that we were not specifying the various weight and styles of the fonts individually within our JavaScript.

As you’ll see in our code above we specify each weight and each weight/style combination individually. Only when all of these are loaded do we use the then function to update the class, create the cookie (so we benefit from browser caching) and the CSS that showing the right font is active. While it would be nice to combine each of these in some array or be able to simply specify the font family name only it doesn’t take much time to specify these individually once you know that you have to.

Why?

Hopefully it should be clear by now that having the text hidden while other assets of the page are loading is a bad idea, if you can avoid it. While sat at the office we don’t have to wait too long for a website to load but this isn’t the case for many people, especially those on a slow connection. Also the FOIT is especially bad on iOS Safari which just compounds the problem. With the website seemingly appearing to load slowly there will be some users who decide they’ve had enough and leave, this obviously affects conversion.

By ensuring the text appears as soon as possible we guarantee that the user can start to consume the information on the page; even if all the page hasn’t finished loading and the fonts suddenly change part way through their experience; this is just Progressive Enhancement. But if we give something for them to do and they can begin to the use the site they will be far less likely to leave and that’s never a bad thing.


We'd love to hear from you!

If you think Bronco has the skills to take your business forward then what are you waiting for?

Get in Touch Today!

Discussion

Add a Comment