📜 ⬆️ ⬇️

Using web fonts, the best way (for 2015)

Recently, I again investigated the issue of loading fonts, since I wanted to use a local copy of the font and make it load as fast and efficient as possible. This approach is significantly different from when you use TypeKit or Google fonts and simple copy / paste snippets.

Over the past months, several articles have been written that address the issue of various techniques for optimizing font loading.

1 , 2 , 3
')
After I read them all, I discovered several new questions that are not addressed in them. In the end, I wanted to have one resource on which information about such problems would be collected. Some snippets of the code are taken or adapted from the articles to which I cited above.

Goals:

  1. Asynchronously load web fonts
  2. Avoid strong recalculation of position in the layout
  3. Upload web fonts as fast as possible
  4. Avoid font downloads for returning visitors.


And now let's try to achieve our goals in stages:

1. Asynchronous Web Font Download


Since you need to call the web font locally via @ font-face, you usually get a blocking request. To avoid it, you need to put the @ font-face code in a separate style sheet, which is invoked via JavaScript. You can use the simple loadCSS function from filamentgroup. This is the easiest option.

You can also use the typefit webfontloader with custom web fonts, which, starting from version 1.6.8, use the native font loading API, if available.

At the moment, we also have Font Face Observer , and also Font Loader , which uses fresh W3C font download events, and we also have a script that uses Smashing Magazine, and which, in fact, solves a few more problems of this article ( But not all).

So where do we start? To begin with, we will exclude Font Loader, providing a polyfill for the latest web standard. It is too big to include in this part of the performance optimization phase. In the future, he will definitely be needed, but if he is not “native,” at the moment it makes no sense to use it. Instead, we can use Font Face Observer. It weighs only 5Kb (it is reduced, not compressed).

Alright, let's get started. You can get the Font Face Observer script via npm, bower or git (hub). Include the script in the head.

Note: Arbitrary setting of the async attribute adds unwanted FOIT to FOUT on your site.

Now we need to initialize the font browser. This can be done using the built-in script, or an external script included in the head. I will show an example that uses the browserify / CommonJS variant in an external script, and the script is loaded as a npm dependency:

First we need to query the library:

var FontFaceObserver = require('fontfaceobserver'); 


Now let's define the fonts and font options that we need to identify:

  var observer = new FontFaceObserver('Fira Sans', { weight: 400 }); 


Here you can use weight, style, variant, featureSettings, stretch as options. Now we need to initialize the Observer to configure the fonts we defined. We also need to set the CSS class to which the font was loaded. This is done through the Promise:

  observer.check().then(function () { document.documentElement.classList.add('webfont-loaded'); }, function () { console.info('Web font could not be loaded in time. Falling back to system fonts.'); }); 


More advanced example with multiple web fonts:
  var fontfaceobserver = require('fontfaceobserver'); var fontObservers = []; var fontFamilies = { 'Fira Sans': [ { weight: 400 }, { weight: 600 } ], 'Fira Mono': [ { weight: 400 } ] } Object.keys(fontFamilies).forEach(function(family) { fontObservers.push(fontFamilies[family].map(function(config) { return new FontFaceObserver(family, config).check() })); }); Promise.all(fontObservers) .then(function() { document.documentElement.classList.add('webfont-loaded'); }, function() { console.info('Web fonts could not be loaded in time. Falling back to system fonts.'); }); 



So we applied the Font Face Observer and set the class of the finished font. Now we need to reflect this in our CSS:

  body { font-family: sans-serif; } .webfont-loaded body { font-family: 'Fira Sans', sans-serif; } 


2. Elimination of a strong recalculation of position in the layout


Now we have an efficient and reliable system into which our web font can be embedded when it is ready. This, of course, means that initially the users will receive the transition font you specified. Despite the fact that this is not bad, as they may already begin to read the text, this means that everything will change before their eyes, which often leads to a displacement of words due to a change in the font.

We need to make the experience more enjoyable. This can be done in two stages:

  1. First you need to find the best transition fonts for your web font. This can best be done with this small bookmarklet and this compatibility check. When you find a good transition font, half the work is done. But there is not a single font that looks the same, and even very similar transitional fonts may have signs of different widths and heights. Fortunately, there are several tools in CSS that allow you to optimize this. There is a new font-size-adjust property that allows you to adjust the transition font to your web font or vice versa. Use it to adjust the height or shape. It's quite difficult to use, so I recommend trying some values ​​in dev tools (or look at the formula in the article I gave the link to if you understand math well). Usually the result is a value between 0.40 and 0.70.
  2. After selecting the height, you need to set up letter-spacing (the distance between letters). This is relatively simple, and if you adjust the value with a small step (for example, -0.01em), you can guarantee that the text will look good and readable. At this point, you should get a transition font visualization that is very similar to a web font. To test the difference in the testing process, you can add a timeout to the function that sets the CSS class for webfont-loaded.


3. Fastest loading of web fonts


This item is quite simple. In fact, we have already done a lot to ensure that our web fonts are loaded as quickly as possible and turned on at the right time. The last thing we can do here is add a preload header for web font files.

  <link rel="preload" href="FiraSans-Regular.woff"> <link rel="preload" href="FiraSans-SemiBold.woff"> 


As you can see, here I only used woff fonts. This is because here we should not call all formats. This small snippet tells the browser that, if possible, it should load these resources. If you add all the formats here, the browser will load them all, which is useless. However, all browsers that support prefetch also support WOFF. If you want to use woff2, please note that it no longer works, so you should avoid adding these headers.

4. Exclusion of font download for returning visitors.


To eliminate the situation when users reload web fonts and do not launch the latest version of JavaScript Font Face Observer, when the font is already available from the cache, you can use cookies or localStorage. If, using cookies, you only check if the font is in the browser's cache, then localStorage places the fonts for longer storage in localStorage and retrieves them from there if the user visits the site again.

I will not give preference to anyone, since both options have their advantages. Although localStorage is more reliable in terms of font caching, it is a little slower than cookies and the browser's native cache. Use what you like best and what will work best in your project.

Use of cookies :

This method is a bit unreliable. The browser’s cache is not directly related to the location where cookies are stored, so if one of them (but not both) is deleted, this method can block the loading of the font.

the simplest code using SSI will look like this:

 <!--#if expr="$HTTP_COOKIE=/webfont-loaded=true/" --> <html lang="en" class="webfont-loaded"> <!--#else --> <html lang="en"> <!--#endif --> 


Using localStorage: you can use this version of the code that Smashing Magazine uses on its website.

Despite the fact that localStorage works quite well, it should be borne in mind that its use may be slightly slower than the use of the native cache, and, more importantly, it takes up space on the user's disk and is created for only one domain. Therefore, if the user goes to another site with the same web font, UA will download it again.

What's next?


As we have noticed in recent months and years, the way we use web fonts is changing all the time. Browsers use Font Load Events, and even CSS properties can be used to help work with FOIT. In the end, font-rendering, font-rendering: swap can greatly simplify everything that I described in this article.

If you want to save a few bytes, eliminating some styles or saturation options, you can try to customize the behavior of the browser, if it allows artificial fonts and there is no font-synthesis.



Source: https://habr.com/ru/post/268771/


All Articles