magentix

Développeur backend indépendant Web, e-commerce, Open-Source, low-tech, indie-web, slow-web, SSG, accessibility, PHP, Python

Billets : Optimiser les web fonts sur son site


Optimiser les web fonts sur son site

Par Matthieu le 22/03/2023

Sélectionner une police légère et optimisée avec uniquement les caractères nécessaires, éviter d'embarquer toutes les versions (gras, italique), de bons moyens pour gagner plusieurs kilo-octets sur les fonts au format WOFF2.


Je me suis interdit pendant de nombreuses années d'utiliser des polices spécifiques sur mes sites, privilégiant les combinaisons de polices système dites "safe" :

"Trebuchet MS", Helvetica, sans-serif
"Times New Roman", Times, serif
"Courier New", Courier, monospace

Car l'intégration d'une police dans ses différents styles (regular, bold, italic) alourdit inévitablement le poids d'une page.

Avec la généralisation massive du format vectoriel WOFF2, j'hésite aujourd'hui un peu moins à proposer une police originale, qui a comme avantages :

Let's go! ( ( (

Poids des polices

Avant de choisir une police pour son site, il est intéressant de s'attarder sur le poids de base du fichier WOFF2 (ce que le client doit télécharger). Les différences sont énormes. Voici un exemple pour 15 polices regular sans-serif populaires :

Poids des polices

Je pense qu'au-delà de 20ko il est préférable de trouver un équivalent plus léger (J'utilisais Ubuntu sur Magentix, j'ai changé pour Poppins !).

Google Fonts

Si je décide de charger une police depuis Google Fonts, par exemple Roboto, Google fournit par défaut un CSS contenant la police découpée en plusieurs langages: Cyrillic, Greek, Vietnamese, Latin, ainsi que leurs caractères étendus.

CSS Google Fonts pour la police Roboto Regular

Le navigateur ne charge que les fichiers dont il a besoin selon les caractères affichés sur la page, grâce au unicode-range précisé dans la déclaration de la police :

/* latin-ext */
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2) format('woff2');
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

Même si cela arrive assez peu souvent, si j'affiche sur une page un seul caractère du unicode-range "latin-ext", je charge (pour Roboto) un fichier supplémentaire de 12ko. C'est assez élevé pour un seul caractère...

Si vous souhaitez utiliser le CDN Google pour héberger le fichier WOFF2, copiez uniquement ce qui concerne la font-face latin dans le CSS de vote site.

Mais le unicode-range utilisé par Google pour générer le WOFF2 est, je trouve, un peu trop étendu...

Unicode Character Ranges

Pour optimiser la police du site, il est donc intéressant de générer un fichier verctoriel WOFF2 ne contenant que les caractères dont vous avez besoin.

Pour percevoir les caractères derrière un unicode-range, j'ai trouvé un outil de Zach Leatherman (11ty) :

Unicode Range Interchange

Cet outil est très pratique pour visualiser les caractères, si besoin en ajouter (Union), ou en supprimer. En ajoutant dans la colonne de gauche le unicode-range pour le langage latin proposé par Google Font, on trouve un grand nombre de caractères jamais (ou très peu) utilisés :

Unicode Range Google Fonts par défaut

En supprimant du fichier WOFF2 ces caractères (en rouge), on économise quelques kilo-octets !

Avec l'outil de Zach Leatherman, on s'apperçoit que le unicode-range suivant est finallement largement suffisant :

U+20-7E,U+C0-FF,U+152,U+153,U+20AC

Ce unicode-range est bien sûre à adpater en ajoutant des caractères si besoin (Espagnol, Roumain...).

Si jamais une page nécessite un caractère non compris dans cet interval, il sera affiché par la police système par défaut indiquée dans la combinaison de fonts (serif, sans-serif, monospace).

Modifier le unicode-range dans la déclaration du font-face dans le CSS ne changera rien au poids de la police, il indique simplement au navigateur les caractères disponibles.

Si vous souhaitez utiliser l'outil de Zach Leatherman en local, j'ai créé une version offline d'un seul fichier (avec l'ensemble des CSS et JS inline) :

unicode-range.zip

TTF vers WOFF2

Pour générer une police au format WOFF2 avec uniquement le unicode-range souhaité, j'ai trouvé principalement des outils Python comme ttf2web ou la librairie fonttools.

On récupère dans un premier temps la police au format TTF, depuis Google Fonts ou autre.

On utilise ici la commande pyftsubset fournie par fonttools pour effectuer la conversion :

pip install fonttools
pyftsubset Roboto-Regular.ttf \
--unicodes=U+20-7E,U+C0-FF,U+152,U+153,U+20AC \
--output-file=Roboto-Regular.woff2 \
--flavor=woff2

On économise pour Roboto Regular 3ko par rapport à la version proposée par Google Fonts (c'est parfois plus selon la police, par exemple 4,5ko pour Raleway).

Reste à charger le nouveau fichier WOFF2 (hébergé localement) dans le CSS du site :

@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(Roboto-Regular.woff2) format("woff2");
}

body {
  font-family: "Roboto", sans-serif;
}

On peut omettre ici le unicode-range, la police étant désormais toujours nécessaire.

Google Font est capable de générer un fichier WOFF2 avec uniquement les caractères souhaités grâce au paramètre text. Par exemple ...?family=Roboto&text=abcABC. Attention cependant, certains caractères spéciaux ne passent pas et le fichier généré n'est pas toujours correct, à utiliser principalement pour [a-z][A-Z][0-9].

Normal, gras et italique ?

Plusieurs versions des polices sont disponibles pour un affichage classique, gras (weight de 100 à 900) ou italique.

Font Weight

Par expérience il n'est pas toujours nécessaire d'embarquer toutes les versions. Les navigateurs sont capables de forcer le style à partir de la police regular. Le rendu est moins qualitatif, mais souvent plutôt correct (à tester selon les polices). Si l'on peut se passer des versions bold et italic, c'est encore mieux !

Voici un exemple avec la police Ubuntu. A gauche la police classique téléchargée par le client. A droite la police Regular forcée en bold, Italic et bold Italic par le navigateur (Chrome).

Font Ubuntu Diff

C'est un choix à faire entre qualité et performance, à adapter selon la situation. Pour une police lourde, si l'italique est peu utilisé sur le site, le rendu dégradé peut être acceptable, et permet (dans cet exemple) d'économiser 67,22 ko. Si la police est légère (par exemple Poppins), ajouter les différentes versions est moins discutable !

Une question ? Rejoignez-moi sur le Fédivers :
@magentix@magentix.space