A short while ago, I’d written about how to load Google fonts locally in order to speed up your site. While we’re on the matter of fonts, we should also consider what happens to text while the fonts haven’t been downloaded yet.
One of the key principles of page speed optimization is that the page should be displayed as soon as possible. That means deferring or inlining CSS whenever possible. We inline all the CSS for “above the page” content and defer the rest.
The Problem with Fonts
However, this approach doesn’t work too well with fonts because of one simple reason – font files are too large to inline into the HTML, and we can’t defer them because they’re needed to render the page! In the recent page speed testing tools, Google has started calling out this problem in the form of the following warning:
The Challenge
What we want in an ideal solution is the following:
- The text should be shown with a “default” font immediately
- The font should be downloaded in the background
- As soon as the font is available, the browser should swap out the default with the new one
Previously, there were all sorts of complicated Javascript solutions to make this happen. It was quite a mess.
Using the “font-display” Directive
In CSS files, the “@font-face” descriptor is used to specify a font. Like this:
@font-face { font-family: 'Arvo'; font-display: auto; src: local('Arvo'), url(...) format('woff2'); }
The “font-display” directive is a new part of “@font-face” that make the magic above happen automatically. It has five possible values:
- auto
- block
- swap
- fallback
- optional
We use it like this:
font-display: optional;
So adding “font-display” to the above block of code would look like this:
@font-face { font-display: optional; font-family: 'Arvo'; font-display: auto; src: local('Arvo'), url(...) format('woff2'); }
Values of “font-display”
Here’s an explanation of the different values of “font-display”.
block (font-display:block)
“Block” is the most restrictive kind of option, and one that we want to avoid unless absolutely necessary. Basically it means that the text will be invisible against the page and will only show up when the necessary font has been downloaded.
This should be used only when having the text in a particular font is necessary, and it simply will not do to have it shown any other way.
swap (font-display:swap)
“Swap” means that the font will be drawn immediately on the page with a fallback font. There is zero “block” time, meaning that the page will not wait at all for the font to load. However, as soon as the required font is available, the browser will “swap” out the fallback text in favor of the new font.
fallback (font-display:fallback)
“Fallback” blocks the browser rendering for a very short period of time – like 100ms. If the font hasn’t yet been downloaded by the time it’s over, the browser will show the fallback font. When the font has finished downloading, it will be swapped out instead of the fallback font.
However, if the font takes too much time to download, then the fallback font will always be used!
optional (font-display:optional)
“Optional” is like fallback, except that it leaves the choice to the browser to decide whether or not to download the font. It’s a good option for low Internet speed users for example.
auto (font-display:auto)
“Auto” simply leaves the option to the browser. This is a bad idea because most browsers currently use “block” as their default!
Support for “font-display”
font-display is supported across all major browser versions. There are a few holdouts like Edge (as of this writing), but it should be quite safe to use for the present and the future.
Impact on Google Page Speed Results
We include the new directive in the @font-face CSS rules like this:
It makes Google happy as in the screenshot below:
A reminder: This is a great reason to load your Google fonts using local CSS, since it allows you to do stuff like this. So go out there and update your web fonts!
I’m a NameHero team member, and an expert on WordPress and web hosting. I’ve been in this industry since 2008. I’ve also developed apps on Android and have written extensive tutorials on managing Linux servers. You can contact me on my website WP-Tweaks.com!
Michael Moriarty says
Excellent solution! I am wondering if you have another article that expounds on loading just the range of characters you need (seems to be what you are doing the in the example with Roboto Slab) and also how you tackle loading fontawesome.
Innocent Cyril says
Thank you so much for showing me how to optimize my Google fonts in my website am now happy
Chris says
Thanks, Bhagwad!
In PageSpeed Insights I’m getting a “Avoid chaining critical requests” warning for the fonts I’ve loaded locally and set at font-display: swap. This is hurting LCP for Core Web Vitals. Have you any idea how I avoid this chaining to minimize LCP?
Bhagwad Park says
Hi Chris. Perhaps try preloading the fonts? Here’s a resource that explains how: https://www.corewebvitals.io/pagespeed/avoid-chainging-ciritical-requests-lighthouse