- Choose the best way to import your Google Fonts
- Skip over some of the latency time for downloading fonts
- Fix flash-of-invisible text (FOIT)
- Self-host your fonts for faster speed and greater control
Anatomy of a Google Fonts request
Let’s take a step back and look at what is happening when you request from Google Fonts using a standard <link>
copied from their website:
<link href=“https://fonts.googleapis.com/css?family=Muli:400“ rel=“stylesheet“/>
Did you notice that the link is for a stylesheet and not a font file? If we load the link’s href into our browser, we see that Google Fonts loads a stylesheet of @font-face
declarations for all the font styles that we requested in every character set that is available. Not all of these are used by default, thankfully.
Then, each @font-face
declaration tells the browser to use a local version of the font, if available, before attempting to download the file from fonts.gstatic.com
Understanding this architecture will help us understand why certain strategies work better for making our site faster.
Should I use <link> or @import?
Sometimes it’s easier for us to get our custom fonts into our projects by importing them in the CSS:
@import url(“https://fonts.googleapis.com/css?family=Open+Sans:400,700”);
Unfortunately, this makes our site load slower because we’ve increased the critical request depth for no benefit. In the network waterfall below, we can see that each request is chained – the HTML is loaded on line 1, which triggers a call to style.css. Only after style.css is loaded and the CSSOM is created will the CSS from Google fonts then be triggered for download. And as we learned in the previous section, that file must also be downloaded and read before the fonts themselves will be downloaded (the final 2 rows):
<head>
of our HTML instead, we can make our load faster because we’ve reduced the number of links in the chain for getting our font files:Warm up that connection faster with preconnect
Look closely at that last waterfall, and you might spy another inefficiency. Go ahead and try to find it before you keep reading…
We have a minimum of 2 separate requests to 2 different hosts — first for the stylesheet at fonts.googleapis.com
, and then to a unique URL for each font hosted at fonts.gstatic.com
.
You may be asking yourself, “Why can’t I just use the direct link to the font?” Google Fonts are updated often so you might find yourself trying to load a font from a link that no longer exists pretty quickly. 🤦🏾
We can make one quick performance improvement by warming up the DNS lookup, TCP handshake, and TLS negotiation to the fonts.gstatic.com
domain with preconnect:
<link rel=”preconnect” href=”https://fonts.gstatic.com/” />
<link rel=”preconnect” href=”https://fonts.gstatic.com/” crossorigin />
<link href=”https://fonts.googleapis.com/css?family=Muli:400″ rel=”stylesheet”/>
Note that the crossorigin
attribute is needed for assets that are loaded in anonymous mode (like fonts). Otherwise, the preconnect will only perform the DNS lookup portion of the connection.
Why? If you don’t warm up the connection, the browser will wait until it sees the CSS call font files before it begins DNS/TCP/TLS:
fonts.gstatic.com
. By adding the preconnect, we can perform DNS/TCP/TLS before the socket is needed, thereby moving forward that branch of the waterfall:<link>
calling your font in your HTML:<link rel=“preconnect“ href=“https://fonts.gstatic.com“ />