Loading Web Fonts
Custom fonts within our application load once the CSS evaluation completes, with Next.js Font Optimization we can tell the browser which fonts to use for the page in a secure way, preload them, and avoid the common performance issues of adding custom fonts.
import { Inter } from '@next/font/google'
const inter = Inter({
variable: '--inter-font',
})
<div className={inter.className}>
...
</div>
Although now our fonts are being preloaded, they will not load immediately. We have a timespan between the font being requested and the font being loaded, that may vary depending on the size of the fonts, the network speed and more.
During this timespan our text will be displayed with a fallback font or with no font at all depending on the font-display
strategy we have defined (more about this in `Font Display` below), by default Next.js will use font-display: optional
and it can be customized with the display
prop.
Based on the visual differences between our custom font and the determined fallback font, we may introduce a layout shift (which is an important metric for Google Core Web Vitals) in our application, as seen in the example below that compares Arial
(left) with Times New Roman
(right):
Fonts with different sizes may create a layout shift in its space and may also push or pull content around it creating a bigger shift in the UI.
One solution is having an adjusted fallback font that tries to match the used space of our custom font to reduce the layout shift. Next.js automatically adds a fallback font that matches your custom font, and you can also do it manually with this tool.
Here we can see the difference that using an adjusted fallback font makes, in a comparison between the Inter
font (left) and a customInter-fallback
font (right) which is Arial
with size-adjust
set to 107%:
Font Display
As we mentioned above, during the timespan between our page displaying text and our custom font being applied to that text, we can choose one of several behaviors that will determine how that text will be displayed, using the display
prop.
display: 'optional'
: The browser will only display the custom font if it is available before it has to start rendering text. If the font is cached it'll be less likely for users to see the fallback font on subsequent visits.
Layout shifts are reduced by using this strategy, as the browser won't swap the fonts after rendering the page with the fallback font. When the fonts are similar enough, this is is the best strategy for a better UX.
If you disable preload
(which triggers a special heuristic and is enabled by default) the font will never be shown in the first page load unless it is in memory cache, even if it is in disk cache.
display: 'block'
: The text will be invisible while the custom font is loading, the reserved space depends on the space that would have been occupied by the fallback font.display: 'swap'
: The browser will display the text using the fallback font while the custom font loads and then swap the fonts once it has finished loading.Learn More
If you want to know more about loading web fonts you can refer to the official docs for Next.js Font Optimization, the API docs for @next/font and this post about font loading by Malte Ubl.