question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Investigate if changing the font loading mechanism is better for users

See original GitHub issue

We currently use font-display: fallback to load our fonts:

This is somewhere in between block and swap. The text is invisible for a short period of time (100ms). Then if the custom font hasn’t downloaded, the text is shown in a fallback font (for about 3s), then swapped after the custom font loads.

Matt’s new font work he has suggested that we change fallback to swap, which is also recommended by performance community members, however when testing in our development environment we have noticed that when the page is switching fonts text “jumps” more than before.

Font-display: swap

After some research I have changed the font-display CSS property from fallback to swap. To quote from Addy Osmani:

…self-hosted Web Fonts have a zero second block period and an infinite swap period. Browsers would draw text immediately with a fallback used if the font face isn’t loaded, but swap as soon as it does load.

More discussion about this change can be seen here, here and here.

We should determine what the difference is to users in the following scenarios, in order of priority:

  1. Users on unreliable slow network connections, with a production optimised server.
  2. Users on a reliable fast network connection, with a production optimised server.

Reference: https://font-display.glitch.me/

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:14 (14 by maintainers)

github_iconTop GitHub Comments

6reactions
Nooshucommented, Feb 24, 2020

Note

This comment overrides any comments / considerations made in PR 1607. The testing method I used in that PR was flawed so the end results weren’t accurate. The method used was to run a very small number of test runs (usually 9), then base results of the median result. The limited number of runs doesn’t give an accurate representation of real-world performance, and can easily introduce large variations.

The updated testing method relies on us using our own WebPageTest instance which gives us the ability to run a lot more tests than the public instance (201 vs 9). This should give us a much more accurate representation.

Hypothesis

Changing font-display: fallback to font-display: swap will improve perceived performance for users.

Reasons for Hypothesis

According to the specification:

swap - Gives the font face an extremely small block period (100ms or less is recommended in most cases) and an infinite swap period.

fallback - Gives the font face an extremely small block period (100ms or less is recommended in most cases) and a short swap period (3s is recommended in most cases).

Now although these two settings look very similar in terms of the specification, practical implementation by browsers is different:

  • With swap there is a 0s blocking period, meaning the fallback font is displayed immediately on first paint. So a user can start reading the content as soon as the page renders. The browser then gets unlimited time to swap out the fallback font for the web font once loaded.
  • With fallback the browser will wait ~100ms before using the fallback font (Arial), in that time the browser will render invisible placeholder text. This 100ms delay to view any content will have a small, but noticeable impact on perceived performance. The browser is given 3 seconds to replace the fallback font with the web font once loaded, else the fallback font will be used for the lifetime of the page.

Others have suggested changing font-display from fallback to swap too. To quote from Addy Osmani:

…self-hosted Web Fonts have a zero second block period and an infinite swap period. Browsers would draw text immediately with a fallback used if the font face isn’t loaded, but swap as soon as it does load.

More discussion about this can be seen here, here and here.

Testing

I will be running 201 test runs over each of 4 GOV.UK pages on production:

The tests will be conducted at 3 connection speeds on Chrome:

  • Cable (5/1 Mbps 28ms RTT)
  • 3G (1.6 Mbps/768 Kbps 300ms RTT)
  • 3G slow (780 Kbps/330 Kbps 200ms RTT)

This should give a fairly representative idea of user experience, since we have a high percentage of users on a 3G or greater effective connection type.

Results

Homepage - Cable

homepage-cable

Test link (GDS internal only access)

Observations

  • swap: full page painted with the fallback font visible immediately at 500ms. Web font loaded at 900ms.
  • fallback: page started paint at 600ms, invisible text for 100ms the fallback font used. Web font loaded at 900ms.

Winner: swap

Homepage - 3G

homepage-3g

Test link (GDS internal only access)

  • swap: page rendered complete with fallback font at 2.9 seconds. Web font loaded at 4.4 seconds.
  • fallback: page rendered complete with fallback font at 2.8 seconds. Web font loaded at 4.4 seconds.

Winner: fallback

Homepage - 3G Slow

homepage-3gslow

Test link (GDS internal only access)

  • swap: page rendered complete with fallback text at 5.1 seconds. Web font loaded at 9.2 seconds.
  • fallback: page rendered complete with fallback text at 5.2 seconds. Web font wasn’t rendered as it passed the 3 second cut-off point.

Winner: swap


Guidance page - Cable

guidance-cable

Test link (GDS internal only access)

  • swap: full page painted with the fallback font visible immediately at 600ms. Web font loaded at 1100ms.
  • fallback: page started paint at 600ms, invisible text for 100ms the fallback font used. Web font loaded at 1100ms.

Winner: swap

Guidance page - 3G

guidance-3g

Test link (GDS internal only access)

  • swap: complete page rendered with fallback text at 2.5 seconds. Web font loaded at 4.2 seconds.
  • fallback: page rendered with invisible text at 2.5 seconds. 100ms later the fallback text was rendered. Web font loaded at 4.1 seconds.

Winner: swap

Guidance page - 3G Slow

guidance-3gslow

Test link (GDS internal only access)

  • swap: page rendered complete with fallback font at 4.3 seconds. Web font loaded at 9.1 seconds.
  • fallback: page rendered with invisible text at 4.2 seconds. 100ms later fallback text rendered. Web font wasn’t rendered as it passed the 3 second cut-off point.

Winner: fallback


Start page - Cable

start-cable

Test link (GDS internal only access)

  • swap: at 600ms page renders with fallback text immediately visible. Web font finished loading at 800ms.
  • fallback: initial page renders at 400ms with invisible text. At 500ms fallback test is rendered. Web font finished loading at 700ms.

Winner: fallback

Start page - 3G

start-3g

Test link (GDS internal only access)

  • swap: page rendered with fallback text immediately seen at 2.8 seconds. Web font loaded at 4.2 seconds.
  • fallback: page rendered with invisible text at 2.8 seconds. 100ms later the fallback font was rendered. Web font loaded at 4.2 seconds.

Winner: swap

Start page - 3G Slow

start-3gslow

Test link (GDS internal only access)

  • swap: page rendered with fallback font at 4.1 seconds. Web font rendered at 8.5 seconds.
  • fallback: page rendered with invisible text at 5.4s. 100ms later fallback text is displayed. Web font wasn’t rendered as it passed the 3 second cut-off point.

Winner: swap


Speech page - Cable

speech-cable

Test link (GDS internal only access)

  • swap: page renders with fallback text immediately visible at 500ms. Web font loads at 800ms.
  • fallback: initial page renders with invisible text at 500ms. Fallback text visible at 600ms. Web font loads at 800ms.

Winner: swap

Speech page - 3G

speech-3g

Test link (GDS internal only access)

  • swap: page rendered with fallback text immediately seen at 2.5 seconds. Web font loaded at 4.1 seconds.
  • fallback: page rendered with invisible text at 2.5 seconds. 100ms later the fallback font was rendered. Web font loaded at 4.1 seconds.

Winner: swap

Speech page - 3G Slow

speech-3gslow

Test link (GDS internal only access)

  • swap: page rendered with fallback text immediately at 3.9 seconds. Web font loads at 9.2 seconds.
  • fallback: page rendered with invisible text at 3.9 seconds. 100ms later the fallback text was rendered. Web font wasn’t rendered as it passed the 3 second cut-off point.

Winner: swap

Summary

The table below gives a summary of the results above. Which font-display property results in the best perceived performance:

Page Cable 3G 3G Slow
Homepage swap fallback swap
Guidance Page swap swap fallback
Start Page fallback swap swap
Speech Page swap swap swap

Chrome performed as per the spec:

  • swap: shows a 0s blocking period and shows fallback text immediately. The browser then waits as much time as needed to load the web fonts before swapping them out (as seen in the 3G Slow tests).
  • fallback: in almost all cases the initial page is rendered with invisible text, then 100ms later the text is replaced with the fallback text. We can see the 3 second cut-off point in action in the 3G Slow tests, where the web font is downloaded by never actually rendered.

Recommendation: change the font-display value from fallback to swap. Our users will be able to see the fallback font (Arial) immediately, without having to see FOIT for 100ms as seen with fallback.

This shouldn’t hugely effect other areas since users will already be seeing the fallback font before the web font has loaded, only after 100ms rather than immediately. This also gives slow connections the chance to render the web font. Since they are already downloading it, they may as well see it at some point. If the last point is a point of contention then we should consider using font-display: optional. This shows exactly the same 100ms of invisible text as seen with fallback, only the browser has the option to choose not to download the font at all. It’s worth noting that this value is hardly used across the web, so I question its effectiveness.

In regards to HTTP/1.1 vs HTTP/2, this shouldn’t really come into the decision. The use of HTTP/2 will make it more likely that the web font is delivered in a decent time, but it won’t change the upfront rendering as controlled by swap vs fallback.

1reaction
Nooshucommented, Dec 4, 2020

I’ve just had an article published in this years Web Performance Calendar all about this issue.

Data shows we could have users on incredibly slow connections in the UK, for which the font loading could take large amount of time. The shift between fallback & webfont is quite significant (especially for v1) and a setting of swap will allow the browser to replace the fallback font with the webfont at any point in the future after the page has ‘settled’. The shift that occurs can be seen visually and detected in DevTools. fallback allows for a maximum of 3 seconds, before the webfont isn’t swapped.

To quote from the article:

So I’d personally prefer to take a hit of 100ms on our LCP, where an invisible font is rendered before showing our fallback font (i.e. font-display: fallback), than potentially causing users on very slow connections a delayed font shift (i.e. font-display: swap)

So I’d say we stick with font-display: fallback and close this issue. Can be opened again in the future if we have significant data to prove otherwise.

Read more comments on GitHub >

github_iconTop Results From Across the Web

The Best Font Loading Strategies and How to Execute Them
Loading fonts from Google Fonts is slightly better because it provides font-display: swap . Here's an example where we load Lato from Google...
Read more >
A Comprehensive Guide to Font Loading Strategies
We want control over which fonts load and when. ... This variation of the Critical FOFT approach simply changes the mechanism through which ......
Read more >
Best practices for fonts - web.dev
This article discusses performance best practices for fonts. There are a variety of ways in which web fonts impact performance:.
Read more >
FOIT vs FOUT: a comparison on web font loading - Rock Content
FOIT vs. FOUT: we compared the two mechanisms of page loading! Learn how each one works and how to choose the best option...
Read more >
The Performance and Usability of Font Loading - YouTube
Slides at https://speakerdeck.com/zachleat/the-performance-and-usability- of - font -loadingMore talks and posts on http://www.zachleat.com/web/
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found