Avoid Layout Shift By Loading Fonts This Way.

Bhavesh Rawat
3 min readJun 5, 2024

--

Photo by Pankaj Patel on Unsplash

Lately, I have been building a lot of static websites as personal projects and for clients using Astro and totally loving it. I came across a website of an UX designer, built on Wix, the performance score on lighthouse, as you’d expect were not good. So, I decided to pitch my static web development service to the potential client, but before that thought of building the homepage prior to it as it wasn’t much.

While building the homepage, I used a library called ‘astro-font’ as I was eyeing on it for a while. This library is inspired by the Next.js Font Optimization and makes sure that no layout shift happens and performance remains top-notch. I can vouch for it now that I have used the library.

Analytics of a webpage scoring high in all PageSpeed Insight criteria
Page Analytics using PageSpeed Insights

Now that I was done with the homepage, I started sniffing in the preview build to see what was this library doing differently that it could score this good and if I could replicate this on my personal website (I did) that is built on vanilla JavaScript. It didn’t take much time to figure out what was going on.

There are two things different about the library’s approach:

  1. Way the fonts are being downloaded.
  2. Way the CSS (for the font) is being declared in the HTML.

How the fonts are being downloaded?

The answer to this was right in the <head> tag. The fonts were being preloaded using the as="font" attribute of the <link> tag.

<link
as="font"
rel="preload"
href="localurl/fontcdn"
type="font/woff2"
crossorigin=""
/>

The usual way is to hook the CSS file with the HTML file and make font request with other properties using font-face at-rule. Here, the rel="preload" itself becomes responsible for force-setting a connection to the URL, which is also fast because the first thing that is getting parsed by the browser is HTML. Here, crossorigin attribute is source dependent. It is needed if you’re using CDN services like Google Fonts, Adobe Fonts, and all.

Now that the connection has been set-up to the source, all we gotta do is call for the resources via styles, and this is where second step comes in.

How the CSS for fonts is being declared?

The CSS for fonts is being declared right inside the <head> tag too. This technique is also termed as Inline CSS, where the style tag is used to declare the styling without having the need of external CSS file. The HTML parser takes the responsibility of serving the styles to the browser which also happens to be the relatively fast way to apply styling.

<head>
<style>
@font-face {
font-family: "Roboto Condensed";
src: url("cdn") format("woff2");
font-weight: 100 900;
font-display: swap;
font-style: normal;
}
body {
font-family: "Roboto Condensed", sans-serif;
}
</style>
</head>

This practice leads to fast style cascading over the DOM whereas the “linked stylesheet” waits for the HTML parser to finish so it can start with the CSSOM building.

The combination of these two can lead to happy layouts and prevent any kind of shifting that would’ve happened from the fonts. It is important to take the hero section (first fold) into account and optimize the markup according to that. After you’re done with the optimization, the difference will be significant.

Comparison between Layout Shift and no Layout Shift
Image Credit: Author

I have already started doing this with two of my projects and will be doing this on all my personal and client projects. You can visit my website and check the real-time performance.

Note: I am available to take on gigs. Click on the link down below.

I am not part of the Medium Partner Program because of demographics. If you like my stuff, support me here or get your Surfshark VPN from this link. Thanks:)

--

--

Bhavesh Rawat

22 • Frontend Engg. • Tech Enthusiast • Blogger • Curator