My font loading strategy
For a long time my font-loading strategy involved using Web Font Loader to avoid FOIT.
I would add following snippet in the document <head>
:
<script>
(function(d) {
if (sessionStorage.webfont) {
d.documentElement.classList.add('wf-active');
return;
}
window.WebFontConfig = {
custom: { families: [ 'my-font:n4' ] },
active: function() { sessionStorage.webfont = true; }
};
const wf = d.createElement('script');
const ref = d.scripts[0];
wf.async = true;
wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
ref.parentNode.insertBefore(wf, ref);
})(document);
</script>
And my CSS looked something like this:
@font-face {
font-family: 'my-font';
src:
url('fonts/my-font.woff2') format('woff2'),
url('fonts/my-font.woff') format('woff'),
url('fonts/my-font.ttf') format('truetype');
font-weight: 400;
font-style: normal;
}
body {
font-family: sans-serif;
}
.wf-active body {
font-family: 'my-font', sans-serif;
}
¶ font-display
When font-display
property was introduced to CSS, I quickly added it to my existing setup.
@font-face {
font-family: 'my-font';
src:
url('fonts/my-font.woff2') format('woff2'),
url('fonts/my-font.woff') format('woff'),
url('fonts/my-font.ttf') format('truetype');
font-weight: 400;
font-style: normal;
+ font-display: swap;
}
if (sessionStorage.webfont
+ || "fontDisplay" in document.documentElement.style) {
d.documentElement.classList.add('wf-active');
return;
}
And now, when font-display
is widely supported my font loading strategy looks like this:
@font-face {
font-family: 'my-font';
src:
url('fonts/my-font.woff2') format('woff2'),
url('fonts/my-font.woff') format('woff'),
url('fonts/my-font.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
body {
font-family: 'my-font', sans-serif;
}
I find this works great for me most of the time. There can be an issue with loading multiple fonts where each font causes a new repaint. In that case, it’s advisable to fall back onto a JS-based approach but I don’t do it by default.
¶ Cloud-hosted fonts
Today, Google Fonts support font-display
so that’s great. On top of it, I like to de-prioritize fonts from critical styles by asyncronosly loading CSS file with @font-face
definitions:
<head>
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin>
<link rel="preload" href="https://fonts.googleapis.com/css?family=Fira+Mono&display=swap" as="style" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Fira+Mono&display=swap"
media="print"
onload="this.media='all'">
</head>
That’s how I load monospace font used in code examples on this blog. I use same approach at Hugo where a single typeface (that we self-host) is used across multiple products.