Optimiser le chargement et l'affichage de WebFont

Ilya Grigorik
Ilya Grigorik

Une WebFont "complète" qui inclut toutes les variantes stylistiques dont vous n'avez peut-être pas besoin, ainsi que tous les glyphes, qui peuvent ne pas être utilisés, peut facilement entraîner un téléchargement de plusieurs mégaoctets. Dans cet article, vous découvrirez comment optimiser le chargement des WebFonts afin que les visiteurs ne téléchargent que ce qu'ils utiliseront.

Pour résoudre le problème des fichiers volumineux contenant toutes les variantes, la règle CSS @font-face est spécialement conçue pour vous permettre de diviser la famille de polices en une collection de ressources. Par exemple, des sous-ensembles Unicode et des variantes de style distinctes.

Compte tenu de ces déclarations, le navigateur détermine les sous-ensembles et les variantes requis, puis télécharge l'ensemble minimal requis pour afficher le texte, ce qui est très pratique. Toutefois, si vous n'êtes pas prudent, cela peut également créer un goulot d'étranglement des performances dans le chemin de rendu critique et retarder le rendu du texte.

Comportement par défaut

Le chargement paresseux des polices comporte une implication cachée importante qui peut retarder le rendu du texte. Le navigateur doit construire l'arborescence de rendu, qui dépend des arborescences DOM et CSSOM, avant de savoir quelles ressources de polices il a besoin pour afficher le texte. Par conséquent, les requêtes de polices sont retardées bien après d'autres ressources critiques, et le navigateur peut être empêché de générer du texte tant que la ressource n'est pas récupérée.

Chemin critique de rendu de la police

  1. Le navigateur demande le document HTML.
  2. Le navigateur commence à analyser la réponse HTML et à créer le DOM.
  3. Le navigateur détecte les fichiers CSS, JS et autres ressources, puis distribue les requêtes.
  4. Le navigateur crée le CSSOM une fois que tout le contenu CSS a été reçu et le combine à l'arborescence DOM pour créer l'arborescence de rendu.
    • Les requêtes de polices sont distribuées une fois que l'arborescence de rendu indique les variantes de polices nécessaires pour afficher le texte spécifié sur la page.
  5. Le navigateur effectue la mise en page et peint le contenu à l'écran.
    • Si la police n'est pas encore disponible, il est possible que le navigateur n'affiche aucun pixel de texte.
    • Une fois la police disponible, le navigateur peint les pixels du texte.

La "course" entre la première peinture du contenu de la page, qui peut être effectuée peu de temps après la création de l'arborescence de rendu, et la demande de la ressource de police est ce qui crée le "problème de texte vide", où le navigateur peut afficher la mise en page de la page, mais omettre tout texte.

En préchargeant WebFonts et en utilisant font-display pour contrôler le comportement des navigateurs avec les polices indisponibles, vous pouvez éviter les pages vides et les décalages de mise en page dus au chargement des polices.

Précharger vos ressources WebFont

Si votre page a de fortes chances d'avoir besoin d'une WebFont spécifique hébergée sur une URL que vous connaissez à l'avance, vous pouvez utiliser la priorisation des ressources. L'utilisation de <link rel="preload"> déclenche une requête pour la WebFont au début du chemin de rendu critique, sans avoir à attendre la création du CSSOM.

Personnaliser le délai d'affichage du texte

Bien que le préchargement augmente la probabilité qu'une WebFont soit disponible lorsque le contenu d'une page est affiché, il n'offre aucune garantie. Vous devez toujours tenir compte du comportement des navigateurs lors de l'affichage d'un texte qui utilise un font-family qui n'est pas encore disponible.

Dans l'article Éviter le texte invisible pendant le chargement des polices, vous pouvez constater que le comportement par défaut du navigateur n'est pas cohérent. Toutefois, vous pouvez indiquer aux navigateurs modernes comment ils doivent se comporter à l'aide de font-display.

Navigateurs pris en charge

  • Chrome : 60.
  • Edge: 79.
  • Firefox: 58.
  • Safari : 11.1.

Source

Comme les comportements de délai avant expiration des polices existants que certains navigateurs implémentent, font-display segmente la durée de vie d'un téléchargement de police en trois périodes principales:

  1. La première période correspond à la période du bloc de polices. Pendant cette période, si la police n'est pas chargée, tout élément qui tente de l'utiliser doit s'afficher avec une police de remplacement invisible. Si la police se charge correctement pendant la période de blocage, elle est ensuite utilisée normalement.
  2. La période de changement de police a lieu immédiatement après la période de blocage de la police. Pendant cette période, si la police n'est pas chargée, tout élément qui tente de l'utiliser doit s'afficher avec une police de remplacement. Si la police se charge correctement pendant la période de remplacement, elle est ensuite utilisée normalement.
  3. La période de défaillance de la police se produit immédiatement après la période de remplacement de la police. Si la police n'est pas encore chargée au début de cette période, elle est marquée comme chargement échoué, ce qui entraîne le remplacement normal de la police. Sinon, la police est utilisée normalement.

Comprendre ces périodes vous permet d'utiliser font-display pour décider de la façon dont votre police doit s'afficher en fonction de son téléchargement ou de son absence.

Pour utiliser la propriété font-display, ajoutez-la à vos règles @font-face:

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  font-display: auto; /* or block, swap, fallback, optional */
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2'), /* will be preloaded */
       url('/fonts/awesome-l.woff') format('woff'),
       url('/fonts/awesome-l.ttf') format('truetype'),
       url('/fonts/awesome-l.eot') format('embedded-opentype');
  unicode-range: U+000-5FF; /* Latin glyphs */
}

font-display est actuellement compatible avec la plage de valeurs suivante:

  • auto
  • block
  • swap
  • fallback
  • optional

Pour en savoir plus sur le préchargement des polices et la propriété font-display, consultez les posts suivants:

L'API Font Loading

Utilisés ensemble, <link rel="preload"> et le CSS font-display vous offrent un contrôle important sur le chargement et le rendu des polices, sans ajouter beaucoup de frais généraux. Toutefois, si vous avez besoin de personnalisations supplémentaires et que vous êtes prêt à accepter les frais généraux liés à l'exécution de JavaScript, il existe une autre option.

L'API de chargement des polices fournit une interface de script pour définir et manipuler les polices CSS, suivre la progression du téléchargement et remplacer leur comportement de chargement différé par défaut. Par exemple, si vous êtes sûr qu'une variante de police particulière est requise, vous pouvez la définir et demander au navigateur de lancer une récupération immédiate de la ressource de police:

Navigateurs pris en charge

  • Chrome: 35.
  • Edge: 79.
  • Firefox: 41.
  • Safari: 10.

Source

var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {
  style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});

// don't wait for the render tree, initiate an immediate fetch!
font.load().then(function() {
  // apply the font (which may re-render text and cause a page reflow)
  // after the font has finished downloading
  document.fonts.add(font);
  document.body.style.fontFamily = "Awesome Font, serif";

  // OR... by default the content is hidden,
  // and it's rendered after the font is available
  var content = document.getElementById("content");
  content.style.visibility = "visible";

  // OR... apply your own render strategy here...
});

De plus, comme vous pouvez vérifier l'état de la police (via la méthode check()) et suivre la progression de son téléchargement, vous pouvez également définir une stratégie personnalisée pour l'affichage du texte sur vos pages:

  • Vous pouvez suspendre l'affichage de tout texte jusqu'à ce que la police soit disponible.
  • Vous pouvez implémenter un délai avant expiration personnalisé pour chaque police.
  • Vous pouvez utiliser la police de remplacement pour débloquer le rendu et injecter un nouveau style qui utilise la police souhaitée une fois qu'elle est disponible.

Mieux encore, vous pouvez combiner les stratégies ci-dessus pour différents contenus de la page. Par exemple, vous pouvez retarder l'affichage du texte dans certaines sections jusqu'à ce que la police soit disponible, utiliser une police de remplacement, puis réafficher le texte une fois le téléchargement de la police terminé.

Un bon cache est indispensable

Les ressources de polices sont généralement des ressources statiques qui ne sont pas mises à jour fréquemment. Par conséquent, elles sont idéales pour une expiration de durée max-age longue. Assurez-vous de spécifier à la fois un en-tête ETag conditionnel et une stratégie Cache-Control optimale pour toutes les ressources de police.

Si votre application Web utilise un service worker, la diffusion de ressources de polices avec une stratégie de mise en cache prioritaire est adaptée à la plupart des cas d'utilisation.

Vous ne devez pas stocker de polices à l'aide de localStorage ou de IndexedDB, car chacun d'eux présente son propre ensemble de problèmes de performances. Le cache HTTP du navigateur fournit le mécanisme le plus efficace et le plus robuste pour fournir des ressources de police au navigateur.

Checklist de chargement des polices Web

  • Personnalisez le chargement et l'affichage des polices à l'aide de <link rel="preload">, font-display ou de l'API Font Loading:le comportement par défaut du chargement paresseux peut entraîner un rendu du texte retardé. Ces fonctionnalités de la plate-forme Web vous permettent d'ignorer ce comportement pour des polices particulières, et de spécifier des stratégies de rendu et de délai avant expiration personnalisées pour différents contenus de la page.
  • Spécifiez des stratégies de revalidation et de mise en cache optimales:les polices sont des ressources statiques qui sont rarement mises à jour. Assurez-vous que vos serveurs fournissent un code temporel de durée de vie longue et un jeton de révalidation pour permettre une réutilisation efficace des polices entre les différentes pages. Si vous utilisez un service worker, une stratégie de mise en cache en premier est appropriée.

Tests automatisés du comportement de chargement des WebFonts avec Lighthouse

Lighthouse peut vous aider à automatiser le processus de vérification que vous respectez les bonnes pratiques d'optimisation des polices Web.

Les audits suivants peuvent vous aider à vous assurer que vos pages continuent de suivre les bonnes pratiques d'optimisation des polices Web au fil du temps: