Custom font usage can introduce cumulative layout shift (or “jank”) to your website. This post shows how to use fontaine to reduce this with Docusaurus sites and will cover:
Cumulative layout shift (CLS) is a metric that measures the instability of content on a web page. It’s a Core Web Vitals metric.
You may well know it as “jank”. It’s jank that you see when a page loads and the text moves around, and it’s a big irritation. There’s a great description of it in this post on the topic; let me quote it here:
Have you ever been reading an article online when something suddenly changes on the page? Without warning, the text moves, and you’ve lost your place. Or even worse: you’re about to tap a link or a button, but in the instant before your finger lands—BOOM—the link moves, and you end up clicking something else!
This, in a nutshell, is what jank is — it’s very frustrating to end users and an issue that we as developers should try to avoid as best we can!
For the rest of this post, I will generally to refer to CLS as jank, as it’s a more relatable term.
My blog uses a custom font called Poppins. Lovely though it is, using the font introduces jank to my site. It’s particularly noticeable on mobile phones. Here’s a gif of the jank in action:
You see how the text shifts around as the custom font arrives? On the first line we either see:
…or:
It’s very noticeable—so noticeable that you can actually put a number on it.
The number is the CLS score which you can determine with Lighthouse. The CLS score is the sum of the layout shifts that occur on the page. The higher the score, the more jank there is. Cumulative Layout Shift was logged as 0.019 for the page above.
That’s not great.
I took some steps to reduce the issues experienced, such as font preloading, but the issues still remained — particularly on mobile networks where speed of loading is decreased and it takes a longer time for the custom font to load.
I had rather given up on improving things further. But then….
One evening I was vaguely browsing Twitter when I came across a tweet from Daniel Roe that announced a new tool called fontaine:
I was intrigued. I wanted to try it out. I wanted to see if it could reduce the jank on my blog by using this tool.
I added fontaine as a dependency to my blog:
yarn add -D fontaine
I then cracked open my docusaurus.config.js
file and wrote a small plugin to make use of fontaine:
const fontaine = require('fontaine'); // ... /** @type {import('@docusaurus/types').Config} */ const config = { // ... plugins: [ // ... function fontainePlugin(_context, _options) { return { name: 'fontaine-plugin', configureWebpack(_config, _isServer) { return { plugins: [ fontaine.fontaineTransform.webpack({ fallbacks: [ 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Open Sans', 'Helvetica Neue', 'sans-serif', ], // You may need to resolve assets like `/fonts/Poppins-Bold.ttf` to a particular directory resolvePath: (id) => '../fonts/' + id, }), ], }; }, }; }, // ... ], // ... };
This didn’t initially seem to make any difference, so I put it up as a work-in-progress PR and wrote up my findings as best I could. Daniel was kind enough to take a look. He uncovered two issues:
- --ifm-font-family-base: 'Poppins'; + --ifm-font-family-base: 'Poppins', 'Poppins override';
Behind the scenes, there is a “Poppins override” @font-face
rule that has been created by fontaine. By manually adding this override font family to our CSS variable, we make our site use the fallback “Poppins override” @font-face
rule with the correct font metrics that finding generates.
It’s worth emphasizing that for the typical user of fontaine, this is not something they need to do. It’s only necessary for Docusaurus users because they use custom fonts through CSS variables. Using fontaine is very plug-and-play for most users.
Daniel was kind enough to raise a PR incorporating both the tweaks. When I merged that PR, I saw the following:
Look at that! You can see the font loading, but there’s no more jumping of words from one line to another. It’s a huge improvement from before!
If you want to improve your CLS score, fontaine is a great tool.
This post demonstrates using it with Docusaurus, but please note that this is a generally useful tool that you can use with Vite, Next.js, and others — it’s not specific to Docusaurus.
Prior to using fontaine, my blog’s Cumulative Layout Shift was logged as 0.019. After incorporating it, the same score is logged as 0. This is good news!
I’m very grateful to Daniel for his help in getting it working with my blog. He went above and beyond, so thank you, Daniel!
In testament to what a great idea fontaine is built upon; in the time I’ve been writing this post, @next/font
has been announced, which is based upon a similar idea.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
ElectricSQL is a cool piece of software with immense potential. It gives developers the ability to build a true local-first application.
Leptos is an amazing Rust web frontend framework that makes it easier to build scalable, performant apps with beautiful, declarative UIs.
Learn more about the 5 best JavaScript libraries for dealing with multidimensional arrays, such as ndarray, math.js, and NumJs.
We spoke with Dom about his approach to balancing innovation with handling tech debt and to learn how he stays current with technology.