Introduction
I’ve been working with Astro quite a bit lately, and the lack of something like next/font
has been a persistent headache. My website was suffering from CLS (Cumulative Layout Shift) issues on the initial page load, especially before the fonts were cached.
Initial Thoughts and Failed Attempts
Initially, I thought, “Oh, maybe next/font
leverages some browser API or meta tag to solve this.” I figured I could probably replicate similar logic in Astro.
However, after experimenting with various approaches like font-display: swap
, fallback
, optional
, preloading fonts, and even serving fonts locally, I still couldn’t achieve the desired results.
The Solution: astro-font
My problems were finally solved when I discovered astro-font
. It seemed that astro-font
and next/font
share a similar mechanism. Curiosity got the better of me, so I dove into the source code to understand how it works. Here’s a breakdown:
How astro-font
(and next/font
) Work
-
Font Downloading and Caching: The package downloads fonts from Google Fonts (or uses local fonts) and caches them.
-
Preload in Header: It adds a preload tag to the document header for the font.
-
Font Metrics and Fallback Generation: This is the core of the solution. It utilizes font metrics (such as
size-adjust
,ascent-override
,descent-override
, andline-gap-override
) and thefontkit
library to create a fallback font from the original font. This fallback font is derived from a local font that closely matches the dimensions of the original font. By default, it will useArial
for sans-serif fonts andTimes New Roman
for serif fonts. Here’s an example:body { font-family: 'Poppins', 'fallback for Poppins', 'another fallback for Poppins'; } @font-face { font-family: 'fallback for Poppins'; src: local('Arial'); ascent-override: 105%; descent-override: 35%; line-gap-override: 10%; }
-
Rendering with Fallback: The browser initially renders the text using the fallback font. When the original font is fully loaded, the browser swaps the fallback font with the original. Because the fallback and original fonts have very similar dimensions, CLS is significantly minimized.
Further Reading on Font Metrics and Fallback Fonts
To learn more about font metrics and the background of font fallbacks, check out this excellent article from the Chrome team.
References
- Implementation of
astro-font
- Implementation of
next/font
- Google Doc on how font fallback is done in next/font
- Font fallbacks - Chrome for Developers
-
nuxt-modules/fontaine
-
unjs/fontaine
Conclusion
astro-font
provides an elegant solution to font loading and CLS issues in Astro, mirroring the approach used by next/font
. By leveraging font metrics and carefully crafting fallback fonts, it ensures a smooth user experience with minimal layout shifts. Understanding the inner workings of these tools can empower developers to optimize web performance and deliver visually stable web pages.