“The Compromise”—a Modern but Compatible Font Loading Strategy
Let’s be frank: the next evolution in advanced web font loading is overdue. I’m not talking about font-display
, which is great—a quick and easy win for introductory font loading. I’m talking about evolving our multi-stage font loading approaches to squeeze every last drop of performance out of our web font rendering.
The next evolution will come when we retire our font loading polyfills.
Retirement Benefits
Polyfill retirement is the next step and is especially important as these JavaScripts are usually inlined in the critical path. The time spent parsing and executing polyfill JavaScript is essentially wasted on browsers that support the native CSS Font Loading API. For example, take the following two examples from my web-font-loading-recipes
repository:
fout-with-class-polyfill.html
using a polyfill:8.46 KB
(uncompressed)fout-with-class.html
using only the CSS Font Loading API:2.17 KB
(uncompressed)
No… Please—Don’t go?
Can we just remove the polyfills wholesale and switch our code to use the CSS Font Loading API? Well, not quite yet. The browser-provided CSS Font Loading API has pretty broad support and has been around for a long time but is confoundedly still missing from all available versions of Microsoft Edge.
Web Browser | CSS Font Loading Support Added |
---|---|
Chrome v35 | May 19, 2014 |
Opera v22 | June 2, 2014 |
Firefox v41 | September 21, 2015 |
Samsung Internet v4 | April 18, 2016 |
UC Browser v11.8 | August 16, 2016 |
Mobile Safari v10 | September 12, 2016 |
Safari v10 | September 19, 2016 |
Internet Explorer | 🚫 Not supported |
Microsoft Edge | 🚫 Not supported |
Microsoft Platform status has given no signals of intent to implement. At time of writing, the CSS Font Loading API UserVoice entry (a voting platform for developers to help Microsoft prioritize features) has 796 votes, which is #49 on the list (ordered by total votes). That’s 350 votes behind the Web MIDI API and 553 votes behind Scrollbar Styling 🙄.
Ahem, I digress.
Fonts for Auction
How do we go polyfill-less in modern browsers without completely sacrificing our web fonts on IE and Edge? This blog post would be pretty silly if it ended without answering that question…
In September of 2017, eBay engineers Senthil Padmanabhan (@senthil_hi) and Raja Ramu (@rajaramu) wrote a blog post titled eBay’s Font Loading Strategy. It may have been one of the most underrated font loading blog posts of 2017.
The eBay strategy was novel for two reasons, the first being that it emulated font-display: optional
using JavaScript. JavaScript was important because at that time only Chrome supported the font-display
descriptor. Practically speaking, font-display: optional
means that an empty-cache view kicks off requests for web fonts but doesn’t render them. Web fonts are only rendered when they are already in available in cache. This minimizes both FOIT and FOUT, as well as nasty text reflows.
The second novelty was that it took steps to partially eliminate polyfill usage! Namely it did not inline a font loading polyfill! Instead it used the CSS Font Loading API if it was available and if not, asynchronously loaded the font loading polyfill to load the web fonts (again, only on IE and Edge).
I’ve also added the eBay Method to web-font-loading-recipes
if you want to check out the code.
The Compromise
Senthil and Raja’s eBay method is great! However, I would make one small change to their approach (and this is also why I don’t prefer font-display: optional
)—I like rendering web fonts on an empty cache load! Thus, the Compromise is born, borrowing heavily from eBay’s approach.
If you’ve been following along at The Comprehensive Guide to Font Loading Strategies, you may be aware that my personal favorite method is currently transitioning to Critical FOFT with preload, given that preload support is on the cusp of widespread support.
Curious what FOFT is? Check the Web Font Loading Glossary.
Let’s Frankenstein the eBay method and the Critical FOFT method together:
You can review the HTML and Lazy loaded JavaScript (only used if the CSS Font Loading API is not supported). The Compromise is also on web-font-loading-recipes
.
In this example, we used a traditional 4+1 Lato setup: Roman (plus a super subset A-Za-z
Roman), Italic, Bold, Italic Bold.
- Preload the super subset Roman (WOFF2)
- If
sessionStorage
key exists for repeat views, add thefonts-loaded-2
class and stop here! - If CSS Font Loading API is supported, load the fonts:
- Use CSS Font Loading API to load Stage 1: super subset Roman
- Render super subset Roman (add
fonts-loaded-1
class) - Use CSS Font Loading API to load Stage 2: Roman, Italic, Bold, and Italic Bold.
- Render Roman, Italic, Bold, and Italic Bold versions (add
fonts-loaded-2
class) - Skip to step 5.
- If CSS Font Loading API is not supported, load the fonts:
- Asynchronously lazy load the polyfill (in this example
critical-foft-preload-fallback-optional.js
) - Use the polyfill to load only Stage 2: Roman, Italic, Bold, and Italic Bold.
- Do not render these fonts (no classes added)
- Skip to step 5.
- Asynchronously lazy load the polyfill (in this example
- All the fonts have confirmed to be loaded, add the
sessionStorage
key for repeat views.
In the wild
It’s frustrating that Microsoft browsers don’t support the CSS Font Loading API. But this is where The Compromise shines—it allows us to serve and render web fonts using the CSS Font Loading API (no polyfills) on an empty-cache page loads. If a browser doesn’t support the CSS Font Loading API (uh, IE and Edge) we take a more relaxed font-display: optional
-ish repeat-view approach.
The Compromise has been battle tested. It has been in production on this web site for quite some time (zachleat.com) and is the strategy we used for the font loading on the lovely redesign of Smashing Magazine (although with FOFT instead of Critical FOFT).
Keep those web fonts frosty, y’all 👍.
Addendum
If some of the terms in the above article were new to you, you may want to look them up on the Web Font Loading Glossary.
4 Comments
@paulkruczynski
It may be. Reading these again in a new context, I might be using the wrong method on this project. I don’t have much control over the fonts. Just trying to get them to not use google fonts, but I may have to let it go
@paulkruczynski
Thank you for responding. It’s appreciated!
@zachleat
Make sure you use `preconnect`! You should check out this talk about the wins you can get with google fonts: zachleat.com/web/five-whys/ The preconnect stuff starts at Slide 50
@ChrisFerdinandi
Thank you!!