Typography is a powerful tool. Consider the number of typography based logos, the popularity of Gary Hustwit’s documentary film Helvetica, the ongoing jokes around Comic Sans, or the fact that Typography legend, Matthew Carter, won a $500K Macarthur Genius Grant. Microsoft has even sponsored a set of studies on 'Measuring the Aesthetics of Reading', that show readers' emotional reactions and task performance can change based on the font they're using.
It's clear: typography can affect our emotions, our comprehension, and even our behavior.
Performance pressure: does typography matter?
Google research from March 2016 showed that 53% of users will bounce from a page if it takes more than 3 seconds to load. Furthermore, over half of site visits now come from users on mobile devices—and potentially slower networks—increasing the risk of higher bounce rates.
Performance, or page speed, can make or break online businesses.
Lately, webpage font use has come under scrutiny for its potentially negative performance impact. Custom fonts—fonts which must be loaded onto the page, as opposed to readily available system fonts—were flagged as bulky resources that slow down page load. Some Google Partner literature has even advised against using custom fonts on mobile sites.
However, on Google and MMA Germany's list of the fastest mobile sites, 7 of the top 10 winners use custom fonts, and two who do not, still make use of custom typography on images (a known accessibility issue). It's clear that custom typography is crucial for user experience, as even the world's highest performing sites are not willing to sacrifice it—so why are these sites so fast?
First and foremost, these sites have controlled for all of the greatest performance bottlenecks: image weight (hogging nearly 63% of page weight on average), multiple server requests (especially problematic if the page displays ads requested from separate partners), and finally, resource-loading. This is the category fonts fall into—but it's important to note that fast font-loading alone will not solve performance problems!
So what's the issue with font-loading? Certain resources, like stylesheets, or web/server hosted custom fonts can be 'render-blocking'. This means, without any optimization of their loading process, the browser may wait to 'paint' the webpage view (render it) until they are loaded. Perhaps even more problematic, a browser may load certain graphics, but leave 'invisible' text on a page.
Measuring font performance impact
To learn how fonts can affect performance and how to remove this risk, we're going to put two versions of the 2017 ecentricarts Holiday card to the test.
First, let's measure the site's performance without font-loading optimization. According to Google's Lighthouse extension, the page graphics load in just over 2 seconds, but the fonts are not loaded and don't arrive until 3 seconds into the load time. There appears to be some font-loading lag.
To see exactly why this is happening, we can open the Network tab in Chrome DevTools to assess the font loading:
The graph section on top shows our markup and CSS resources loading as the browser builds the tree of information (DOM) that will display on the page. After the DOM is loaded, a 'DOMContentLoaded' event is fired (indicated with the blue arrows), triggering the CSS, and allowing font load to start. The page isn't complete (indicated with the red arrow) until the final fonts have loaded.
In this case, the fonts are being loaded after the DOM is constructed and the CSS code from our stylesheet calls them in. This explains the lag and that flash of invisible text—it's the period of time between the fonts being called, and their load time.
Again, but with the magic of preoloading
How can we prevent this pesky font lag? Fonts can be preloaded! Preloading tells the browser to start loading fonts before the DOM tree is even constructed. This ensures that the second these fonts are called, they're already available.
To contrast the previous example, let's run a Chrome DevTools analysis of our Holiday card again. This time, our fonts are preloaded, and render-blocking resources, deferred:
According to the tool, the fonts begin to load almost immediately, before the DOM tree is complete. This means on first paint, they are immediately available. You'll also notice the first paint comes earlier; that's because we've used font-display preferences that tell the browser to go ahead and start painting—there's no need to wait for the fonts.
With a few tweaks, preloading allows custom fonts to be just as fast as system fonts instead of becoming render-blocking resources.
The difference can be seen when we revisit Google Lighthouse, too. Now, the user sees all the custom text immediately upon the page rendering—no delays, and no invisible text.
But wait, it gets even better! As impactful as preloading can be, it's also a really quick win. It requires very little code and is relatively easy to implement. It's such an important part of development, that Google Lighthouse recently added preloading to their list of speed test criteria.
The preload code
Add this link to the head of your index.html where you would usually add fonts:
<link rel="preload" href="/fonts/MyFont-Black.woff" as="font" type="font/woff" crossorigin>
Call the font you've loaded in your css, and set the font-display property to either fallback or swap, which tells the browser not to wait for a font if one isn't available, but use a system font instead. Font-display is the key to reducing render-blocking. This might make a flash of system font appear, however since we're preloading, we can avoid this:
font-family: MyFont Black;
src: url('../../fonts/MyFont-Black.woff') format('woff');
Use that font name (variable) in your css with your standard fallback stack:
font-family: MyFont Black, sans-serif;
Preloading with the Google Fonts library
First, paste the font link URL into a browser to see the @font-face rules
From these rules, grab the font URLs you want and add them to your preload link:
<link rel="preload" href="https://fonts.gstatic.com/s/raleway/v12/QAUlVt1jXOgQavlW5wEfxQLUuEpTyoUstqEm5AMlJo4.woff2" as="font" type="font/woff2" crossorigin>
Next, add the @font-face rules you need to your css. Consider limiting unicode ranges
, requesting a local font
first, in case the user has already viewed a site with that font and has is loaded, and customizing font-display preferences
src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v12/JTUSjIg1_i6t8kCHKm459WlhyyTh89Y.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
Ready for a browser near you
It's really that easy. But there's always a catch, right? Does this work for all browsers? According to CanIuse, all modern browsers, except IE11, Opera, and UC support it.
What about mobile users? According to statCounter, there are no North American mobile users on IE11, while the UC and Opera browsers garner only 0.86%, and 0.5% of the market. Assuming clients still want to ensure there is ZERO extra delay for ANY user, and prioritize site speed over the look and feel of their website for 1.46% of the mobile market, these browsers' font families can be targeted specifically to use system fonts, while the rest of their users can enjoy preloading technology.
I hope you're excited as we are about lightning-fast font-loading! At the end of the day, all stakeholders in a project—clients, managers, designers and developers—will have to make decisions about what aspects of user experience are most important to them.
Fortunately, technology has solved many of the problems we used to have around resource loading and making beautiful, performant sites easier to achieve. With these tips, we hope that font-loading will become the least of your worries.
*Addendum: As IE11 only supports woff, not woff2, make sure to add a Woff declaration in your @fontface rule. For cross-browser support, post your google font into chrome and IE and make sure you add both into your CSS. The woff2 first and if there is no support then the browser will step through to the next font which is woff.