avatarManuel Matuzovic

Summary

The article provides an introduction to the CSS Font Loading API, discussing its benefits for web font management and control over font loading behavior compared to traditional @font-face methods.

Abstract

The article "Getting started with CSS Font Loading" by Manuel Matuzovic explores the capabilities of the CSS Font Loading API as an improvement over the traditional @font-face method for embedding web fonts. The author explains that while @font-face allows for lazy loading of fonts, it lacks control over font loading and rendering, leading to inconsistent behavior across browsers. The CSS Font Loading API addresses these issues by providing developers with the ability to define, add, and load fonts programmatically, track their loading status, and handle loading events. This enables more efficient font management, improved performance, and a better user experience. The article also points out that browser support for the API is already substantial, and for cases where support is insufficient, developers can use solutions like Font Face Observer as a fallback.

Opinions

  • The author, Manuel Matuzovic, views the CSS Font Loading API as a significant advancement, treating web fonts as an enhancement and accepting system fonts for older or less capable browsers.
  • Matuzovic appreciates the control provided by the CSS Font Loading API, particularly the ability to track font loading progress and manage lazy loading according to developer preferences.
  • There is an acknowledgment that while the native CSS Font Loading API is preferable, Bram Stein's Font Face Observer remains a valuable tool for ensuring broader compatibility.
  • The author expresses a desire for future CSS-based solutions for font loading, such as the font-display property, but notes that widespread support for such features will likely take time.

Getting started with CSS Font Loading

I was in the mood to learn something new and so I decided to take a look at the CSS Font Loading API.

You may ask yourself why I chose CSS Font Loading. Well, because up until now I hadn’t taken the time and browser support is already pretty great. At least for me it’s good enough because I treat web fonts as an enhancement and I’m fine with older or less capable browsers serving system fonts.

Before I show you how it works, I want to really quickly review the state of web font loading and explain why we need something like CSS Font Loading. If you are not into reading (at the moment), here’s a CodePen for you.

Disclaimer: This article isn’t meant to be a deep dive into the API, but a quick start and a glance at some of the features.

The problem with @font-face

Before CSS Font Loading there was only one way for us to natively load and embed webfonts, the @font-face rule and the font-family property.

The good thing about @font-face is that fonts are loaded lazily, but the bad thing about @font-face is that fonts are loaded lazily.

Let me explain that: When you add a @font-face rule to your CSS in almost all browsers (IE8 is an exception) pretty much nothing happens [1]. Not until you declare this font somewhere in your CSS with font-family. That's good because fonts don't get downloaded needlessly if they aren't in use. What's bad about it is that we can't control what happens between the initial request and the font being rendered. We give it up to browsers completely and they behave quite differently [2]. This is where CSS Font Loading comes into play.

How CSS Font Loading works

The CSS Font Loading API gives us the ability to add fonts, track their download progress and handle lazy loading the way we want it. If you have used Bram Steins Font Face Observer before, this will be very familiar to you.

Defining and adding FontFaces It’s pretty much like defining a @font-face rule. The first argument is the family, the second the source(s) and the third optional descriptors (style, weight, stretch, unicodeRange, variant, featureSettings).

var notoSansRegular = new FontFace('Noto Sans Regular', 'url(/fonts/NotoSans-Regular.woff2)', {
    style: 'normal',
    weight: '400'
});

If you want to use the FontFace, you have to add it to the so called FontFaceSet which is available as document.fonts[3].

document.fonts.add(notoSansRegular);

Loading a FontFace After defining and adding a font, you can load it whenever you want and/or need it.

notoSansRegular.load();

Of course, you can define, add and load multiple FontFaces.

Tracking the status of the FontFace and the FontFaceSet Declaring and adding FontFaces was easy. The fun part is tracking their status because this is where we can decide on the what, when and how.

[FontFace].status returns the current status (unloaded, loading, loaded or error);

console.log(notoSansRegular.status);

As soon as the font is loaded and ready, the loaded Promise resolves.

notoSansRegular.loaded.then((fontFace) => {
  // This is where you can declare a new font-family, because the font is now loaded and ready.  
  console.info('Current status', fontFace.status);
  console.log(fontFace.family, 'loaded successfully.');
// Throw an error if loading wasn't successful
}, (fontFace) => {
  console.error('Current status', notoSansRegular.status);
});

loaded will only tell us when a single given font is loaded and ready, but we might want to be informed when all fonts are ready, if there are multiple. The earlier mentioned FontFaceSet has the ready attribute, which contains a Promise that resolves when the document is done loading all fonts.

document.fonts.ready.then((fontFaceSet) => {
  console.log(document.fonts.size, 'FontFaces loaded.');
});

Easy cheesy, right? As soon as the fonts are ready, you can apply the font-family via JavaScript or add a class, that does that for you, or do whatever you want. You can see all of that in action in this CodePen. Of course, there are more things you can do with the API, but in most cases you'll be fine with loading fonts and knowing when they are ready.

Browser support and closing thoughts Browsers that don’t understand this technique will see a fallback system font and we are not necessarily talking about Arial or Times here, there are way more of them than you might think there are.

If you don’t ride the progressive enhancement train and the current browser support isn’t enough for you, please consider using Bram Steins Font Face Observer.

It’s great to have a native way of controlling font loading, but it still doesn’t feel quite right, because I believe that this should also be possible with CSS. And it will be, but I’m afraid that we’ll have to wait quite a while until the font-display property is ready.

Further reading, sources and resources

1: https://dev.opera.com/articles/better-font-face/ 2: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization#webfonts_and_the_critical_rendering_path 3: https://googlechrome.github.io/samples/font-face-set/

Web Development
Typography
CSS
Webperformance
Front End Development
Recommended from ReadMedium