Introduction
Une belle typographie, ça rend une page web tout de suite plus attractive.
Il est loin le temps des sites en Arial et Times, avec parfois de la Comic Sans (beurk !) pour les plus fantaisistes.
De nos jours, on utilise des webfonts, polices de caractères chargées par le navigateur avec les autres ressources d’une page web. Chaque page peut ainsi avoir ses propres polices, sans être restreinte aux polices installées sur la machine du visiteur.
Cet article présente une technique d’optimisation des webfonts, afin de conserver un chargement de page rapide malgré l’utilisation de polices personnalisées.
Le font subsetting, qu’est ce que c’est ?
Avant de parler du font subsetting, il faut s’intéresser aux polices elles-mêmes. Que trouve t’on à l’intérieur d’un fichier webfont ?
Une police contient des caractères identifiés par un code
La majeure partie d’une webfont est occupée par les caractères (symboles).
Chaque caractère est identifié par un code numérique généralement exprimé en base hexadécimale. Par exemple, la lettre A majuscule a pour code hexadécimal 41. Les codes sont les mêmes quelle que soit la police : le A majuscule a toujours le code hexadécimal 41.
Une webfont contient en général les caractères de plusieurs langues : latines, cyrilliques, arabes, asiatiques… Elle contient aussi des symboles graphiques (puces, icônes).
Variations des caractères : les caractéristiques OpenType de la police
Pour chaque caractère, le designer de la police a la possibilité d’ajouter des variations de ce dernier. Les différents types de variations possibles sont rassemblés sous l’appellation caractéristiques OpenType – en anglais on parle de features.
Ces variations disposent du même code que le caractère de base dont elles dérivent. Par exemple, les variations de la lettre G minuscule auront toutes le code hexadécimal 67. On peut indiquer dans le style CSS quand activer ou ne pas activer une variation particulière, et le moteur de rendu du navigateur se chargera d’afficher la bonne version du caractère.
Une description des features OpenType est disponible sur le site de Mozilla : explication des features OpenType. Il n’est pas nécessaire de trop approfondir (la plupart des sites n’exploitent pas les features) à moins de travailler sur des sites aux typographies complexes.
Définition du font subsetting
Le font subsetting consiste à utiliser une webfont « subset » de la police d’origine qui ne contient que les caractères et les caractéristiques OpenType qui nous intéressent.
Par exemple, sur un site qui ne contient que des caractères français, il est inutile de faire télécharger au visiteur une webfont contenant toute la gamme des symboles chinois.
Cela permet de réduire drastiquement la taille des webfonts. En effet, il y a parfois plus d’un millier de caractères dans une police, avec plusieurs variations pour certains d’entre-eux !
Comment réaliser un subset
Choisir les codes de caractères à inclure dans le subset
La première étape dans la création d’un subset de webfont est le choix des caractères à inclure.
Tout dépend des langues sur le site
Le choix des caractères se fait en fonction des langues présentes sur le site. Sauf cas particulier, on se retrouve dans l’une des situations suivantes :
⚙️ Le site est mono-langue, sans possibilité aux visiteurs de laisser des commentaires. C’est le cas le plus simple, on va inclure dans le subset l’ensemble des caractères de la langue concernée, ainsi que les symboles de ponctuation.
⚙️ Le site est multi-langue, sans possibilité aux visiteurs de laisser des commentaires. Dans ce cas, on va soit inclure l’ensemble des caractères de toutes les langues (ainsi que la ponctuation) dans un seul subset, soit générer un subset pour chaque langue.
⚙️ Le site est mono ou multi-langue, et les visiteurs peuvent laisser des commentaires. C’est le cas le plus complexe. Il faut déterminer quelles seront les langues parlées dans le site et les commentaires, et soit faire un subset incluant les symboles de toutes ces langues (ainsi que la ponctuation), soit faire un subset par langue.
Lister les codes caractères avec la table des blocs unicode
Une fois que l’on a choisi quels caractères conserver, on utilise la table des caractères unicode pour déterminer les codes des caractères. Voici un petit résumé des caractères appropriés aux sites en français :
Nom du bloc | Codes | Contient notamment |
---|---|---|
Basic Latin | U+0000-007F | Minuscules et majuscules sans accent, chiffres, ponctuation et symboles de base (@, #, $, !) |
Latin-1 Supplement | U+0080-00FF | Lettres accentuées communes (é, ï, ñ), ponctuation et symboles communs (£, §, ¡, ¿, «), espace insécable nbsp |
Latin Extended-A | U+0100-017F | œ (U+0153), accents étrangers (ů, ũ) |
General Ponctuation | U+2000-206F | Guillemets élégants (‘, “), puces (•, ‣), primes (‵, ‶, ‷) |
Currency Symbols | U+20A0-20CF | € (U+20AC), devises étrangères (₤, ₿) |
Par exemple, pour un petit site français, on pourra utiliser les caractères U+0000-007F,U+0080-00FF,U+0153,U+20AC
.
Trouver les caractères présents sur un site avec glyphhanger
L’outil nodejs glyphhanger permet de lister les caractères présents sur une page web ou sur un site entier. Ca permet d’éviter d’oublier certains caractères spéciaux (tiens, il y avait un symbole de puce ici !).
Il peut être installé via le gestionnaire de packages NodeJS npm. La documentation indique qu’il faut aussi installer pyftsubset, mais ce n’est obligatoire que si on veut générer un subset directement depuis glyphhanger, ce qui n’est pas notre cas.
# Installation de glyphhanger (peut demander un sudo)
npm install -g glyphhanger
# Alternative non-root
npm install glyphhanger
Son utilisation pour lister les caractères en ligne de commandes est simple :
# Déterminer les caractères présents sur une seule page
glyphhanger https://example.com/
# Déterminer les caractères présents sur un site (3 niveaux)
glyphhanger https://example.com/ --spider-limit=3
# Résultat :
# U+A,U+20,U+2E,U+44,U+45,U+4D,U+54,U+59,U+61,U+63-69,U+6B-70,U+72-79
Il ne faut pas limiter le subset aux codes de caractères renvoyés par glyphhanger ! Ce n’est pas parce qu’un site ne contient pas la lettre Z pour l’instant qu’elle ne sera pas utilisée plus tard !
On limitera son utilisation à détecter s’il y a des caractères spéciaux (hors alphabet et symboles communs) à inclure.
Déterminer les caractéristiques à conserver
Pour déterminer les caractéristiques à conserver, il faut déjà connaitre celles qui sont présentes dans la police d’origine. On peut utiliser pour cela l’analyseur de police Wakamai Fondue.
Sans action de notre part, les features OpenType actives sur une page web sont le Kerning kern
, les Contextual Alternates calt
et les Ligatures liga
et clig
. Il est préférable de toujours les conserver.
L’analyse révèle parfois des caractéristiques requises (en anglais Required Layout Features). Il est possible de les conserver également. Cependant, elles sont souvent requises uniquement pour certains langages (cyrilliques, asiatiques), et peuvent être omises pour les subsets en langues occidentales.
Pour les autres caractéristiques, elles ne sont appliquées que si elles sont activées dans style CSS. On peut donc déterminer si elles sont utilisées en explorant les styles du site à la recherche des instructions associées :
Instruction CSS | Caractéristique OpenType |
---|---|
font-kerning | Kerning : kern |
font-variant-ligatures | Ligatures : liga , clig , dlig , hlig , calt |
font-variant-position | Mise en exposant et indice : sups , subs |
font-variant-alternates | Styles alternatifs : salt , ss01..ss20 |
font-variant-caps | Petites capitales : smcp , c2sc , pcap , unic , titl |
font-variant-numeric | Chiffres et fractions : ordn , zero , lnum , onum , pnum , tnum , frac , afrc |
font-variant / font-feature-settings | Potentiellement toutes, lire le CSS |
Sur de nombreux sites ces caractéristiques ne sont pas utilisées. Pour reprendre l’exemple du petit site français, on pourrait sans doute se limiter à conserver les features kern,calt,liga,clig
.
Générer le subset avec les caractères et les features
Une fois que l’on a choisi quels caractères et quelles features OpenType conserver dans notre subset, il est temps de le générer. Cela peut se faire en ligne ou localement.
Génération de subset en ligne avec Font Squirrel
Le mode expert du générateur de webfont Font Squirrel permet d’extraire un subset d’une police, et de le générer dans différents formats. Malgré son appellation, il reste simple à utiliser pour ce que l’on veut faire. Il n’arrive parfois pas à retirer certaines caractéristiques OpenType, mais permet tout de même de bien réduire la taille des webfonts.
Cliquez sur l’image ci-dessous pour voir une capture d’écran des réglages de font subsetting. Pour résumer, tout est désactivé sauf ce qui concerne le choix des caractères et des features, et les formats sont WOFF et WOFF2 (on peut se limiter au format WOFF2 si le support de Internet Explorer n’est pas souhaité).
Génération de subset en local avec pyftsubset
Pour générer localement un subset on peut utiliser l’outil pyftsubset disponible dans le package python des fontTools. Il peut être installé via les gestionnaires pip ou pip3. Par exemple, pour la version Python 3 :
# Installation des fontTools (peut demander un sudo)
pip3 install fonttools[woff,unicode]
# Alternative non-root
pip3 install fonttools[woff,unicode] --user
Une fois installé il est assez simple à utiliser, à moins que l’on veuille se perdre dans toutes les possibilités qui sont offertes par l’outil. La documentation en ligne est plutôt bien fournie.
Si on reprend l’exemple du petit site français pour lequel on a estimé qu’il fallait un subset avec les caractères U+0000-007F,U+0080-00FF,U+0153,U+20AC
et les features kern,calt,liga,clig
, la commande est la suivante :
# Création d'un subset
# - Format WOFF2
# - Caractères U+0000-007F, U+0080-00FF, U+0153 et U+20AC
# - Caractéristiques OpenType kern,liga,clig
pyftsubset police.ttf --unicodes=U+0000-007F,U+0080-00FF,U+0153,U+20AC --layout-features=kern,calt,liga,clig --flavor=woff2 --output-file=police-subset.woff2
On peut aussi supprimer toutes les caractéristiques OpenType, ou bien toutes les conserver :
# Conserver toutes les caractéristiques OpenType
pyftsubset police.ttf --unicodes=U+0000-007F,U+0080-00FF,U+0153,U+20AC --layout-features='*' --flavor=woff --output-file=police-subset.woff
# Supprimer toutes les caractéristiques OpenType
pyftsubset police.ttf --unicodes=U+0000-007F,U+0080-00FF,U+0153,U+20AC --layout-features='' --flavor=woff --output-file=police-subset.woff
On obtient un fichier WOFF ou WOFF2 prêt à être utilisé sur le site internet.
Utiliser le subset en CSS
Les fichiers subset peuvent être utilisés comme n’importe quelle webfont dans le code du site internet. Cela se passe au niveau des styles CSS :
@font-face {
font-family: Roboto;
src: url(fonts/roboto-subset.woff2) format('woff2'), url(fonts/roboto-subset.woff) format('woff');
font-weight: normal; font-style: normal;
}
body{ font-family: Roboto }
On peut utiliser l’instruction unicode-range à l’intérieur de la définition @font-face pour indiquer quels sont les caractères présents dans le subset. C’est totalement optionnel, à moins d’avoir plusieurs subset pour la même police (un par langue par exemple). Cela permet au navigateur de charger le bon subset en fonction des caractères à afficher.
@font-face {
font-family: Roboto;
src: url(fonts/roboto-francais.woff2) format('woff2'), url(fonts/roboto-francais.woff) format('woff');
font-weight: normal; font-style: normal;
unicode-range: U+0000-007F,U+0080-00FF,U+0153,U+20AC; /* sera utilisé pour les caractères français */
}
@font-face {
font-family: Roboto;
src: url(fonts/roboto-cyrillic.woff2) format('woff2'), url(fonts/roboto-cyrillic.woff) format('woff');
font-weight: normal; font-style: normal;
unicode-range: U+0400-04FF; /* sera utilisé pour les caractères cyrilliques */
}
body{ font-family: Roboto }
Conclusion
Voila, on dispose maintenant des notions et d’une méthodologie pour découper les webfonts en subsets plus légers à charger.
Le prochain article concerne une mise en pratique du font subsetting.
D’ici là bon code à vous, à la prochaine !
Bien entendu, si vous avez besoin d’une aide pour optimiser votre site web, n’hésitez pas à me contacter.
Références
Analyseur de police (caractères et fonctionnalités) – Wakamai Fondue
Guide des caractéristiques de police – Mozilla Developers
Tableau des caractères unicode – Symbl.cc
Glyphhanger – Github
Webfont Generator – Font Squirrel
Pyftsubset ligne de commande – Documentation fontTools