Réduire la taille de police sur le Web

La typographie est essentielle pour une bonne conception, l'image de marque, la lisibilité et l'accessibilité. Les polices Web permettent tout ce qui précède et plus encore : le texte est sélectionnable, consultable, zoomable et compatible avec les écrans haute résolution. Il s'affiche de manière cohérente et nette, quelle que soient la taille et la résolution de l'écran. Les WebFonts sont essentielles pour une bonne conception, une bonne UX et de bonnes performances.

L'optimisation des polices Web est un élément essentiel de la stratégie globale de performances. Chaque police est une ressource supplémentaire, et certaines polices peuvent bloquer le rendu du texte. Toutefois, ce n'est pas parce qu'une page utilise des polices Web qu'elle doit forcément s'afficher plus lentement. Au contraire, les polices optimisées, combinées à une stratégie judicieuse pour leur chargement et leur application sur la page, peuvent contribuer à réduire la taille totale de la page et à améliorer les temps de rendu.

Anatomie d'une police Web

Une police Web est un ensemble de glyphes, et chaque glyphe est une forme vectorielle qui décrit une lettre ou un symbole. Par conséquent, deux variables simples déterminent la taille d'un fichier de police particulier : la complexité des chemins vectoriels de chaque glyphe et le nombre de glyphes dans une police donnée. Par exemple, Open Sans, l'une des WebFonts les plus populaires, contient 897 glyphes, dont des caractères latins, grecs et cyrilliques.

Table des glyphes de la police

Lorsque vous choisissez une police, il est important de tenir compte des jeux de caractères compatibles. Si vous devez localiser le contenu de votre page dans plusieurs langues, vous devez utiliser une police qui offre un aspect et une expérience cohérents à vos utilisateurs. Par exemple, la famille de polices Noto de Google vise à prendre en charge toutes les langues du monde. Toutefois, notez que la taille totale de Noto, avec toutes les langues incluses, donne lieu à un téléchargement ZIP de plus de 1, 1 Go.

Dans cet article, vous découvrirez comment réduire la taille des fichiers de vos polices Web.

Formats de police Web

Deux formats de conteneur de police sont actuellement recommandés sur le Web :

Les formats WOFF et WOFF 2.0 sont largement acceptés et compatibles avec tous les navigateurs modernes.

  • Diffuser la variante WOFF 2.0 aux navigateurs récents.
  • Si cela est absolument nécessaire (par exemple, si vous devez toujours prendre en charge Internet Explorer 11), utilisez le format WOFF comme solution de secours.
  • Vous pouvez également envisager de ne pas utiliser de polices Web pour les anciens navigateurs et de revenir aux polices système. Cela peut également améliorer les performances des appareils plus anciens et plus limités.
  • Étant donné que les formats WOFF et WOFF 2.0 couvrent tous les navigateurs modernes et anciens encore utilisés, il n'est plus nécessaire d'utiliser les formats EOT et TTF, qui peuvent entraîner des temps de téléchargement plus longs pour les polices Web.

Polices Web et compression

Les formats WOFF et WOFF 2.0 disposent d'une compression intégrée. La compression interne de WOFF 2.0 utilise Brotli et offre une compression jusqu'à 30% supérieure à celle de WOFF. Pour en savoir plus, consultez le rapport d'évaluation WOFF 2.0.

Enfin, il convient de noter que certains formats de police contiennent des métadonnées supplémentaires, telles que des informations sur l'hinting et le crénage, qui peuvent ne pas être nécessaires sur certaines plates-formes, ce qui permet d'optimiser davantage la taille des fichiers. Par exemple, Google Fonts propose plus de 30 variantes optimisées pour chaque police et détecte et fournit automatiquement la variante optimale pour chaque plate-forme et navigateur.

Définir une famille de polices avec @font-face

La règle CSS @font-face vous permet de définir l'emplacement d'une ressource de police spécifique, ses caractéristiques de style et les points de code Unicode pour lesquels elle doit être utilisée. Une combinaison de telles déclarations @font-face peut être utilisée pour construire une "famille de polices", que le navigateur utilisera pour évaluer les ressources de police à télécharger et à appliquer à la page actuelle.

Envisagez d'utiliser une police variable

Les polices variables peuvent réduire considérablement la taille des fichiers de vos polices lorsque vous avez besoin de plusieurs variantes d'une police. Au lieu de devoir charger les styles normal et gras, ainsi que leurs versions italiques, vous pouvez charger un seul fichier contenant toutes les informations. Toutefois, la taille des fichiers de police variable sera supérieure à celle d'une variante de police individuelle, mais inférieure à celle de la combinaison de plusieurs variantes. Plutôt qu'une grande police variable, il peut être préférable de diffuser d'abord les variantes de police critiques, puis de télécharger les autres variantes ultérieurement.

Les polices variables sont désormais compatibles avec tous les navigateurs modernes. Pour en savoir plus, consultez Introduction to variable fonts on the web (Présentation des polices variables sur le Web).

Sélectionnez le bon format

Chaque déclaration @font-face fournit le nom de la famille de polices, qui sert de groupe logique pour plusieurs déclarations, les propriétés de police telles que le style, l'épaisseur et l'étirement, ainsi que le descripteur src, qui spécifie une liste hiérarchisée d'emplacements pour la ressource de police.

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome.woff2') format('woff2'),
       /* Only serve WOFF if necessary. Otherwise,
          WOFF 2.0 is fine by itself. */
       url('/fonts/awesome.woff') format('woff');
}

@font-face {
  font-family: 'Awesome Font';
  font-style: italic;
  font-weight: 400;
  src: local('Awesome Font Italic'),
       url('/fonts/awesome-i.woff2') format('woff2'),
       url('/fonts/awesome-i.woff') format('woff');
}

Tout d'abord, notez que les exemples ci-dessus définissent une seule famille Awesome Font avec deux styles (normal et italic), chacun pointant vers un ensemble différent de ressources de police. Chaque descripteur src contient une liste de variantes de ressources séparées par des virgules et classées par ordre de priorité :

  • La directive local() vous permet de référencer, de charger et d'utiliser des polices installées localement. Si l'utilisateur a déjà installé la police sur son système, le réseau est entièrement contourné, ce qui est la méthode la plus rapide.
  • La directive url() vous permet de charger des polices externes. Elle peut contenir un indice format() facultatif indiquant le format de la police référencée par l'URL fournie.

Lorsque le navigateur détermine que la police est nécessaire, il parcourt la liste des ressources fournies dans l'ordre spécifié et tente de charger la ressource appropriée. Par exemple, en suivant l'exemple ci-dessus :

  1. Le navigateur effectue la mise en page et détermine les variantes de police nécessaires pour afficher le texte spécifié sur la page. Les polices qui ne font pas partie du modèle d'objet CSS (CSSOM) de la page ne sont pas téléchargées par le navigateur, car elles ne sont pas nécessaires.
  2. Pour chaque police requise, le navigateur vérifie si elle est disponible localement.
  3. Si la police n'est pas disponible localement, le navigateur parcourt les définitions externes :
    • Si un indice de format est présent, le navigateur vérifie s'il le prend en charge avant de lancer le téléchargement. Si le navigateur ne prend pas en charge l'indice, il passe au suivant.
    • Si aucun indice de format n'est présent, le navigateur télécharge la ressource.

La combinaison de directives locales et externes avec des indications de format appropriées vous permet de spécifier tous les formats de police disponibles et de laisser le navigateur gérer le reste. Le navigateur détermine les ressources requises et sélectionne le format optimal.

Sous-ensemble unicode-range

En plus des propriétés de police telles que le style, l'épaisseur et l'étirement, la règle @font-face vous permet de définir un ensemble de points de code Unicode pris en charge par chaque ressource. Cela vous permet de diviser une grande police Unicode en sous-ensembles plus petits (par exemple, les sous-ensembles latin, cyrillique et grec) et de ne télécharger que les glyphes nécessaires pour afficher le texte sur une page spécifique.

Le descripteur unicode-range vous permet de spécifier une liste de valeurs de plage séparées par une virgule. Chacune de ces valeurs peut se présenter sous l'une des trois formes suivantes :

  • Point de code unique (par exemple, U+416)
  • Plage d'intervalle (par exemple, U+400-4ff) : indique les points de code de début et de fin d'une plage.
  • Plage de caractères génériques (par exemple, U+4??) : ? caractères indiquent n'importe quel chiffre hexadécimal.

Par exemple, vous pouvez diviser votre famille Awesome Font en sous-ensembles latin et japonais, que le navigateur télécharge en fonction des besoins :

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2');
  /* Latin glyphs */
  unicode-range: U+000-5FF;
}

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome-jp.woff2') format('woff2');
  /* Japanese glyphs */
  unicode-range: U+3000-9FFF, U+ff??;
}

L'utilisation de sous-ensembles de plages Unicode et de fichiers distincts pour chaque variante stylistique de la police vous permet de définir une famille de polices composites dont le téléchargement est plus rapide et plus efficace. Les visiteurs ne téléchargent que les variantes et les sous-ensembles dont ils ont besoin. Ils ne sont pas obligés de télécharger des sous-ensembles qu'ils ne verront ni n'utiliseront peut-être jamais sur la page.

Presque tous les navigateurs sont compatibles avec unicode-range. Pour assurer la compatibilité avec les anciens navigateurs, vous devrez peut-être revenir au "sous-ensemble manuel". Dans ce cas, vous devez fournir une seule ressource de police contenant tous les sous-ensembles nécessaires et masquer le reste au navigateur. Par exemple, si la page n'utilise que des caractères latins, vous pouvez supprimer les autres glyphes et diffuser ce sous-ensemble spécifique en tant que ressource autonome.

  1. Déterminez les sous-ensembles nécessaires :
    • Si le navigateur est compatible avec la création de sous-ensembles unicode-range, il sélectionnera automatiquement le bon sous-ensemble. La page doit simplement fournir les fichiers de sous-ensemble et spécifier les plages Unicode appropriées dans les règles @font-face.
    • Si le navigateur n'est pas compatible avec la création de sous-ensembles unicode-range, la page doit masquer tous les sous-ensembles inutiles. En d'autres termes, le développeur doit spécifier les sous-ensembles requis.
  2. Générez des sous-ensembles de polices :
    • Utilisez l'outil Open Source pyftsubset pour créer des sous-ensembles de vos polices et les optimiser.
    • Certains serveurs de polices, comme Google Fonts, créent automatiquement des sous-ensembles par défaut.
    • Certains services de police permettent de créer manuellement des sous-ensembles à l'aide de paramètres de requête personnalisés. Vous pouvez ainsi spécifier manuellement le sous-ensemble requis pour votre page. Consultez la documentation de votre fournisseur de polices.

Sélection et synthèse de polices

Chaque famille de polices peut être composée de plusieurs variantes stylistiques (normal, gras, italique) et de plusieurs épaisseurs pour chaque style. Chacune d'elles peut, à son tour, contenir des formes de glyphes très différentes (par exemple, un espacement ou une taille différents, ou une forme complètement différente).

Épaisseur de la police

Le schéma ci-dessus illustre une famille de polices qui propose trois épaisseurs de gras différentes :

  • 400 (standard)
  • 700 (en gras).
  • 900 (très gras).

Toutes les autres variantes intermédiaires (indiquées en gris) sont automatiquement mappées à la variante la plus proche par le navigateur.

Lorsqu'un poids est spécifié pour lequel aucun visage n'existe, un visage avec un poids proche est utilisé. En général, les épaisseurs en gras correspondent aux visages avec des épaisseurs plus fortes, et les épaisseurs fines correspondent aux visages avec des épaisseurs plus faibles.

Algorithme de mise en correspondance des polices CSS

La même logique s'applique aux variantes italiques. Le concepteur de la police contrôle les variantes qu'il produit, et vous contrôlez celles que vous utiliserez sur la page. Comme chaque variante est un téléchargement distinct, il est préférable de limiter leur nombre. Par exemple, vous pouvez définir deux variantes en gras pour la famille Awesome Font :

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2');
  /* Latin glyphs */
  unicode-range: U+000-5FF;
}

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 700;
  src: local('Awesome Font'),
       url('/fonts/awesome-l-700.woff2') format('woff2');
  /* Latin glyphs */
  unicode-range: U+000-5FF;
}

L'exemple ci-dessus déclare la famille Awesome Font, qui est composée de deux ressources couvrant le même ensemble de glyphes latins (U+000-5FF), mais offrant deux "épaisseurs" différentes : normale (400) et gras (700). Toutefois, que se passe-t-il si l'une de vos règles CSS spécifie une épaisseur de police différente ou définit la propriété font-style sur italic ?

  • Si aucune police ne correspond exactement, le navigateur utilise la police la plus proche.
  • Si aucune correspondance stylistique n'est trouvée (par exemple, aucune variante italique n'a été déclarée dans l'exemple ci-dessus), le navigateur synthétise sa propre variante de police.
Synthèse de polices

L'exemple ci-dessus illustre la différence entre les résultats réels et synthétisés de la police Open Sans. Toutes les variantes synthétisées sont générées à partir d'une seule police de 400 points. Comme vous pouvez le constater, les résultats sont très différents. Les détails sur la façon de générer les variantes en gras et en italique ne sont pas spécifiés. Par conséquent, les résultats varient d'un navigateur à l'autre et dépendent fortement de la police.

Checklist d'optimisation de la taille de police Web

  • Auditez et surveillez votre utilisation des polices : n'utilisez pas trop de polices sur vos pages et, pour chaque police, réduisez au minimum le nombre de variantes utilisées. Cela permet d'offrir une expérience plus cohérente et plus rapide à vos utilisateurs.
  • Évitez les anciens formats si possible : les formats EOT, TTF et WOFF sont plus volumineux que le format WOFF 2.0. Les formats EOT et TTF sont strictement inutiles, tandis que le format WOFF peut être acceptable si vous devez prendre en charge Internet Explorer 11. Si vous ne ciblez que les navigateurs modernes, l'utilisation de WOFF 2.0 uniquement est l'option la plus simple et la plus performante.
  • Créez des sous-ensembles de vos ressources de police : de nombreuses polices peuvent être divisées en plusieurs plages Unicode pour ne fournir que les glyphes dont une page spécifique a besoin. Cela permet de réduire la taille du fichier et d'améliorer la vitesse de téléchargement de la ressource. Toutefois, lorsque vous définissez les sous-ensembles, veillez à optimiser la réutilisation des polices. Par exemple, ne téléchargez pas un ensemble de caractères différent, mais qui se chevauche, sur chaque page. Il est recommandé de créer des sous-ensembles en fonction du script (par exemple, latin et cyrillique).
  • Donnez la priorité à local() dans votre liste src : en listant local('Font Name') en premier dans votre liste src, vous vous assurez qu'aucune requête HTTP n'est effectuée pour les polices déjà installées.
  • Utilisez Lighthouse pour tester la compression de texte.

Effets sur le Largest Contentful Paint (LCP) et le Cumulative Layout Shift (CLS)

En fonction du contenu de votre page, les nœuds de texte peuvent être considérés comme des candidats pour la métrique Largest Contentful Paint (LCP). Il est donc essentiel de s'assurer que vos polices Web sont aussi petites que possible en suivant les conseils de cet article. Vos utilisateurs verront ainsi le texte de votre page dès que possible.

Si vous craignez que le texte de la page mette trop de temps à s'afficher en raison d'une ressource de police Web volumineuse, malgré vos efforts d'optimisation, la propriété font-display propose plusieurs paramètres qui peuvent vous aider à éviter que le texte soit invisible pendant le téléchargement d'une police. Toutefois, l'utilisation de la valeur swap peut entraîner des modifications importantes de la mise en page, ce qui affecte le Cumulative Layout Shift (CLS) de votre site. Si possible, envisagez d'utiliser les valeurs optional ou fallback.

Si vos polices Web sont essentielles à votre image de marque et, par extension, à l'expérience utilisateur, envisagez de les précharger afin que le navigateur puisse les demander plus tôt. Cela peut réduire la période d'échange si vous utilisez font-display: swap ou la période de blocage si vous n'utilisez pas font-display.