Using Google Fonts properly
How and why I have chosen to use Google Fonts.
What happened to variable fonts?
In this post I wrote that I wanted to experiment with variable fonts. After looking online for a good open source variable font, I found the one I wanted to use on my website: Source Sans.
The problem is that I couldn't find a light variable version of
Source Sans in
woff2, so the entire loaded font weighted
123kb. Compared to 2 non-variable font files in
woff2, which weight
26kb combined, and since I'm only using 2
font-weights: 300 and 400 so far. Using non-variable fonts seems to be the way to go.
To host or not to host (the custom fonts)
The answer to this question is not binary. But in our case, taking advantage of a CDN for our fonts has multiple advantages:
- we don't have to optimize the fonts for each browser
- there's a good chance that the font file is already cached by the user's browser, which will reduce the load time.
That is why I decided to use the Google Fonts CDN to import
Source Sans Pro into my website.
FOUT or FOIT?
FOUT stands for
Flash of Unstyled Text. It describes the effect you have before your custom font is loaded and the browser display your text content with the first available font in your
FOIT stands for
Flash of Invisible Text. This strategy hides the text completely before the custom font is loaded.
Based on your preference, you can use
font-display: block; to have
font-display: swap; to have
The font-display css property needs to be set when declaring the
@font-face. Which would be annoying for our choice of using Google Fonts, because the
@font-face is provided by the CDN.
The good news is that Google Fonts recently allowed us to specify a custom
font-display in the css URL.
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400&display=swap" rel="stylesheet" />
we are now able to force
FOUT with a local font that matches the best our custom font.
Having dynamic fonts loaded specifically for the client is great but it comes with a cost: a DNS lookup, a TLS negotiation and a TCP handshake. We can use
preconnect to anticipate the need for those.
At first I tried to add
preconnect to the domain
fonts.gstatic.com. I realized that
dns-prefetch was not needed in my case since
preconnect also does the lookup.
dns-prefetch performs a DNS lookup ahead of time.
preconnect performs DNS lookups, TLS negotiations and TCP handshakes before the HTTP request is made.
This is the code I added in
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin />
This allows my fonts to be loaded faster since the entire connection to the server is done as soon as the
<head> is parsed.
Before without preconnect:
After with preconnect:
Notes about react-snap
While trying to optimize the way the Google Fonts were loaded I noticed that, in production, I had no calls to https://fonts.googleapis.com/ and the 2 fonts downloaded were
.ttf files which weighted each around
The reason for that is
inlineCSS: true. Since
react-snap downloaded all the css files for me in order to inline them, and since it's chrome doesn't seem to have the "latest" headers for font files, Google Fonts was loading
.ttf files as fallback.
inlineCSS: true from the
react-snap configuration and now the font files loaded are
woff2 files, which are around
While inlining the css file from Google Fonts speeds up the page load, it does not load the most optimized font file type for the current client.
Notes about unicode-range subsetting
If you look into a Google Fonts generated css, you'll see that every subset is there. The file is actually ready for all non-latin languages.
Since I my website will only contain latin characters I don't need other subset.
Google Fonts doesn't support adding
&subset=latin in their api URL for browsers which supports unicode-range subsetting, which is now pretty well supported:
The browser actually use this line to figure out what font it should load or not:
While I wanted to optimize every bit of the css that is loaded onto my website, being able to use cached fonts still makes using Google Fonts the better option for me, for now.
The code for the changes I'm mentioning in this post is available on Github in this Pull Request.