Fallback fonts - prevent content jumping


Martin Koparanov

September 19, 2019

Words overlapping

Loading fonts on the web usually takes some time. During this time, you will either see an unstyled font or not see text at all. This makes your content jump around. Don't you hate it when you are browsing a website on your phone and suddenly something loads and shifts the whole page. Now you have lost your scroll position and your patience.

A nice trick you can apply is to set a fallback font (which is available on most systems) and make it match your actual font via CSS properties, such as line-height, font-size, letter-spacing and so on. It will not look like your actual font, but it will take the same space as your actual font. This prevents your content from jumping around.

Font style matcher

There is a cool tool available which you can use to match two fonts. You adjust sliders until the fallback font looks as similar as possible to your actual font. The tool in question is Font style matcher.

After you get a close match, you can easily copy the CSS properties for both fonts.

Applying styles

Usually, when I read about this technique, the explanation ended here. Sure, I got two matching fonts, but what do I do with them?! How do I switch between the two when my actual font is loaded?! How do I even know that my font is loaded?

If you are in the same shoes as I was, fear no more!

The way I did it is to add my fallback styles to the body by default like this

body {
font-family: Arial;
font-size: 16px;
line-height: 1.6;
word-spacing: 1.35px;
letter-spacing: 0.7px;
}

Now, when my actual font has loaded, I would apply a class to the body which now has the styles for the font that I want, like this:

body.montserrat-loaded {
font-family: Montserrat;
font-size: 16px;
line-height: 1.6;
word-spacing: 0px;
letter-spacing: 0px;
}

"Oh, cool! But how do I know when to apply this class?!" you may ask. Hold tight, you will get your answer shortly.

Detecting loaded font

How do we detect when a font has loaded? JavaScript, of course! If you are disgusted at the sight of JavaScript used as a workaround for CSS, don't worry - I am too. I love JavaScript as a whole, but I hate it when it is used for CSS-related workarounds!

Now, you also need to download a tiny library for that...

"What is this?! StackOverflow?!", I hear you cry. No, do not worry, I still haven't told you to just use jQuery!

The library is called fontfaceobserver. This is all the code you need to write! Just replace Montserrat with the font you want!

const font = new FontFaceObserver('Montserrat');
font.load().then(() => {
document.body.classList.add('montserrat-loaded');
});

If you are importing it as a node module, it is a default export

All this does is add a class to the body when the font has loaded. The class which applies your correct styles!

Demonstration

Want to see a live demo? Well, inspect this page (the one you are reading this on) and notice the body has a class "montserrat-loaded". Disable and enable this class. See how the font changes, but the content doesn't jump around? Yeah, this is what you are going after!

Or just paste this into your console and see the magic!

setInterval(() => {
if (!document.body.classList.contains('montserrat-loaded')) {
document.body.classList.add('montserrat-loaded');
} else {
document.body.classList.remove('montserrat-loaded');
}
}, 1000);

Conclusion

That is one simple solution. I know it is not something mind-blowing, but I hope someone who was struggling as much as I was to see this and have a moment of relief. It always feels nice to know you are not the only one!


Categories: Frontend, Tutorial,

Tags: css, html, js,