Zach’s ugly mug (his face) Zach Leatherman

“The Compromise”—a Modern but Compatible Font Loading Strategy

April 05, 2018

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:

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.

  1. Preload the super subset Roman (WOFF2)
  2. If sessionStorage key exists for repeat views, add the fonts-loaded-2 class and stop here!
  3. If CSS Font Loading API is supported, load the fonts:
    1. Use CSS Font Loading API to load Stage 1: super subset Roman
    2. Render super subset Roman (add fonts-loaded-1 class)
    3. Use CSS Font Loading API to load Stage 2: Roman, Italic, Bold, and Italic Bold.
    4. Render Roman, Italic, Bold, and Italic Bold versions (add fonts-loaded-2 class)
    5. Skip to step 5.
  4. If CSS Font Loading API is not supported, load the fonts:
    1. Asynchronously lazy load the polyfill (in this example critical-foft-preload-fallback-optional.js)
    2. Use the polyfill to load only Stage 2: Roman, Italic, Bold, and Italic Bold.
    3. Do not render these fonts (no classes added)
    4. Skip to step 5.
  5. 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.


< Newer
Import your Disqus Comments to Eleventy
Older >
Passing the Lead NebraskaJS Organizer Baton

Zach Leatherman IndieWeb Avatar for https://zachleat.com/is a builder for the web at IndieWeb Avatar for https://cloudcannon.com/CloudCannon. He is the creator and maintainer of IndieWeb Avatar for https://www.11ty.devEleventy (11ty), an award-winning open source site generator. At one point he became entirely too fixated on web fonts. He has given 78 talks in nine different countries at events like Beyond Tellerrand, Smashing Conference, Jamstack Conf, CSSConf, and The White House. Formerly part of Netlify, Filament Group, NEJS CONF, and NebraskaJS. Learn more about Zach »

26 Reposts

IndieWeb Avatar for https://prema.kapilaya.netIndieWeb Avatar for https://imjohnainsworth.comIndieWeb Avatar for https://www.yogitatrainingcenter.comIndieWeb Avatar for https://www.splendidwebsites.comIndieWeb Avatar for https://guidetraffic.netIndieWeb Avatar for https://imaginemarketingonline.esIndieWeb Avatar for https://imaginemarketingonline.esIndieWeb Avatar for https://nice-space.comIndieWeb Avatar for https://br.atsit.inIndieWeb Avatar for http://marketingtumbler.comIndieWeb Avatar for https://wpwerk.comIndieWeb Avatar for https://www.new.pixel-forge.caIndieWeb Avatar for https://susmartech.comIndieWeb Avatar for https://www.seowebdesignllc.comIndieWeb Avatar for https://www.smashingmagazine.comIndieWeb Avatar for https://business2020.xyzIndieWeb Avatar for http://adharidshop.liveIndieWeb Avatar for https://gsensenews.comIndieWeb Avatar for http://niclink.irIndieWeb Avatar for https://hostulum.comIndieWeb Avatar for https://webdesign.idjgie.xyzIndieWeb Avatar for https://www.smashingmagazine.comIndieWeb Avatar for https://allprowebdesigns.comIndieWeb Avatar for https://www.webmastersgallery.comIndieWeb Avatar for https://smartphonephotography.inIndieWeb Avatar for http://unsorted.co

3 Likes

jalbertbowdeniiChris Ferdinandi ⚓️nils binder 🏳️‍🌈
4 Comments
  1. Paauł Kruczynski

    @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

  2. Paauł Kruczynski

    @paulkruczynski

    Thank you for responding. It’s appreciated!

  3. Zach Leatherman

    @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

  4. Chris Ferdinandi ⚓️

    @ChrisFerdinandi

    Thank you!!

Shamelessly plug your related post

These are webmentions via the IndieWeb and webmention.io.

Sharing on social media?

This is what will show up when you share this post on Social Media:

How did you do this? I automated my Open Graph images. (Peer behind the curtain at the test page)