Face à face avec les webs fonts

Introduction

Le contenu et sa présentation constituent des éléments essentiels d'une application web pour garantir une expérience utilisateur réussie.
Pour renforcer l'identité visuelle de votre site, vous devez proposer une typographie adaptée. Cela est rendue possible par la personnalisation des fonts.

En tant que développeur, choisir et implémenter les bonnes polices sur un site web peut sembler être une simple tâche de design. Mais il y a des arbitrages à faire, des questions à se poser pour choisir la bonne approche car un mauvais usage peut ralentir les performances et impacter l'expérience utilisateur. Cet article explore comment utiliser les fonts efficacement pour allier design et performance, tout en garantissant une navigation fluide.

Local versus Online

Implémentations

Il est possible de déclarer des fonts hébergées dans votre projet. Une fonctionnalité CSS arrivée en 2016 nous permet cela : @font-face.

Voici comment l'implémenter :

@font-face {
font-family: 'MaPolice', sans-serif;
src: url('ma_police.woff2') format('woff2'),
url('ma_police.woff') format('woff');
}

"font-family" correspond au nom que vous souhaitez donner à votre police, c'est ce nom qui sera utilisé dans les feuilles de styles. Est indiqué également dans notre cas une fallback font, police de secours au cas où la première ne serait chargée (voir plus d'informations).

"src" contient les sources de vos polices, il est possible d'indiquer plusieurs sources de différents formats pour assurer la meilleure compatibilité possible. Nous reviendrons sur ce point plus loin dans cet article.

Vous pouvez utiliser une ressource en ligne pour une font dans les métadonnées de notre page web :

<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">

Ou dans une feuille de style via un import :

@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');

Format de font et compatibilité

Avec un service online comme Google Fonts, pas besoin de s'attarder sur la compatibilité de la police avec le navigateur. C'est en revanche un point sur lequel il faut se pencher quand on héberge nos propres fonts.

Voici les principaux formats que l'on retrouve, il y en a d'autres mais il ne sont plus d'utilité aujourd'hui :

TTF (TrueType Font) : Format de police destiné à un usage local, non compressé, principalement utilisé dans les systèmes d'exploitation et les logiciels hors ligne.

WOFF (Web Open Font Format) : c'est un format de police compressé optimisé pour le web..

WOFF2 : c'est une nouvelle version de WOFF avec une compression encore plus efficace, réduisant davantage la taille des fichiers.

Le format .WOFF et .WOFF2 sont désormais bien pris en charge par les navigateurs actuels (respectivement 97% et 96%).

L'utilisation la plus optimale pour assurer la meilleure compatibilité est d'utiliser le format .woff2 et de définir une fallback font au format .woff.

Optimisation

Partez léger !


Vous l'aurez compris pour le web, il faut utiliser une font compressée, cela permettra un chargement plus rapide et un impact environnemental plus faible. Pour vous donner une idée du gain entre ces différents formats, prenons un exemple avec la font "Roboto" :

Comparaison de taille des fonts:
.ttf pèse 168 kilo octet, .woff pèse 93 kilo octet, .woff2 pèse 66 kilo octet

Faire le tri !

Il est essentiel d'analyser ses besoins en termes de variantes (épaisseurs du trait, italique,...). En effet ne gardez que les fonts essentielles, il serait dommage de charger l'ensemble de ses variantes si seulement quelques-unes sont utilisées.

Néanmoins pour une interface réussie et une meilleure expérience utilisateur, il est utile d'inclure les fonts avec variantes plutôt que de compter sur l'interprétation du navigateur pour afficher une variante (pour le gras ou l'italique par exemple).
Ci dessous, un test illustrant mon propos à partir d'une même font. À gauche avec des fonts dédiées, et à droite sans.


Il y a également un autre axe d'optimisation assez conséquent, la font contient un ensemble de caractères pour différents alphabets (latin, cyrillique, …). La plupart seront inutilisés sur votre application, il est donc nécessaire de ne garder que l'essentiel.

Je vous conseille de choisir le subset "latin" pour une utilisation sur un site en français qui pourra être traduit en anglais, allemand, espagnol, italien...

J'ai utilisé le site transfonter.org pour faire cette optimisation et voici le poids final de la font "Roboto" déjà cité en exemple dessus. Un fichier html est également généré pour tester notre configuration.

Comparaison de taille des fonts avec le subset latin:
.woff pèse 22 kilo octet contre 93 kilo octet sans subset, .woff2 pèse 17 kilo octet contre 66 kilo octet sans subset

On ne part pas sans roue(s) de secours !

Il est utile d'ajouter une fallback font qui servira à garantir l'affichage de votre contenu au cas où votre ressource principale rencontre un problème.

Il peut être intéressant de définir également une fallback font locale (qui est installé sur le système). Il est même possible de récupérer la font utilisée sur le système d'exploitation avec la valeur "system-ui".

body { font-family: 'MaPolice', system-ui; }

Il est possible de chercher une font se rapprochant de l'originale via ces 2 ressources, cela permettra de garder une interface plus fidèle à l'originale :

Cache me if you can

Un autre aspect de l'optimisation est la mise en cache, en effet une fois vos polices mises en cache, les temps de chargement seront réduits au minimum !

Pour ce faire, vous pouvez utiliser l'entête HTTP Cache-Control en ciblant les fichiers de polices. Voici un exemple pour une configuration avec un serveur Nginx :

server {
    location ~* \.(woff|woff2|ttf)$ {
        expires 1y;  # Le cache est valable pendant un an
        add_header Cache-Control "public, max-age=31536000";
    }
}


Enfin utiliser une font depuis Google Font par exemple présente un autre avantage, si le client a déjà téléchargé cette police depuis Google Font durant sa navigation sur d'autres sites, cette police sera déjà disponible en cache et il n'aura pas besoin de la re-télécharger.

Préchargement

Il est possible de prioriser le téléchargement des ressources en utilisant l'attribut "rel" d'un link :

<!--  
Si la font est importé dans la feuille de style:
-->  
<link rel="stylesheet preload" href="style.css" as="style">

<!--  
Si c'est une  ressource de type feuille de style :
-->  

<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet preload" as="style">

<!--  
Ou bien pour une ressource de type font :
-->  
 
<link rel="preload" href="/assets/Pacifico-Bold.woff2" as="font" type="font/woff2" crossorigin>


Cela permettra de s'assurer que la font sera appliquée le plus tôt possible. Attention cette pratique est à utiliser avec précaution, la mémoire utilisée n'est donc plus allouée à d'autres ressources.

Problèmes que l'on peut rencontrer

En utilisant les optimisations proposées ci-dessus, les risques de se retrouver confrontés aux 2 problèmes que nous allons évoquer sont réduits au maximum.

Un Flash of Invisible Text (FOIT) se produit quand le navigateur affiche le texte de façon invisible le temps que la police soit téléchargée et soit rendue.

On peut configurer le comportement du navigateur avec la propriété CSS suivante :

font-display: swap

La valeur "swap" indique au navigateur qu'il chargera le rendu immédiat de la police avec la police par défaut.
Cette solution peut paraître efficace puisque le texte est rendu même si la font n'est pas encore disponible. Mais cela va engendrer l'apparition du second problème : Flash of Unstyled Text (FOUT).

Vous l'aurez compris il va causer un changement soudain de style de texte, cela peut changer la mise en forme et perturber l'utilisateur dans sa navigation (layout shift).

Ce phénomène peut aussi se produire en absence de stratégie de display des fonts, chaque navigateur a un comportement par défaut.

Pour conclure cette partie sur l'optimisation, il est possible de minimiser l'apparition de ces problèmes au maximum. Toutefois cela peut se produire ne serait-ce que si la connexion de l'utilisateur est lente par exemple.
En dernier recours, définissez une font de secours se rapprochant au maximum de la police finale pour ne pas perturber la navigation (voir Section "On ne part pas sans roue(s) de secours!" ci dessus).

Maintenant que nous avons traité ensemble le sujet du choix des fonts, voyons comment garantir une mise en page du texte fluide et flexible à l'aide des unités.

Pourquoi relative plutôt que absolue : la bataille des unités

Comparaison des unités relatives et absolue

C'est une question qui revient très souvent, nous allons voir quel choix d'unité est le plus pertinent pour notre texte.

On distingue aujourd'hui deux catégories d'unités: absolue (px) ou relative (rem,em,...).

Les unités absolues sont indépendantes du contexte dans lesquelles elles sont utilisées. Elles ne tiennent pas compte des paramètres de l'utilisateur.

À l'inverse, les unités relatives dépendent de ce contexte. En effet, l'écran ou encore les préférences de l'utilisateur sont prises en compte.

Nous allons étudier le comportement d'un texte défini avec une taille de police absolue (px) ou relative (rem) :

Avec une configuration par défaut, taille de police définie dans le navigateur à 16px :

On remarque ici que la taille est identique que l'unité soit absolue ou relative.

Prenons désormais le cas d'une configuration avec une taille de police définie à 32px préférences du navigateur :

Le paragraphe dont la taille est définie en rem(unité relative) suit les préférences de l'utilisateur, contrairement au texte dont la taille est définie en px(unité absolue).

Ainsi pour proposer à vos utilisateurs la même expérience, il est nécessaire d'utiliser une unité relative pour votre texte afin de suivre leur préférence.

Mais alors quelle unité relative choisir ?

Il existe plusieurs unités relatives: rem, em, %.

rem et em sont assez similaires mais ont une différence notable: leur référence. En effet, rem est basée sur la font-size définie à la racine (par défaut les préférences de l'utilisateur), alors qu'em a pour référence la font-size de l'élément courant.

Enfin la taille exprimée en % est équivalente à une expression avec em. En effet, une font-size de 100% équivaut à 1em.

Utilisez donc rem en général et em quand vous voulez de la proportionnalité entre un conteneur et un élément enfant.

Choisir sa font

Famille de font

On distingue les familles de font suivantes :

  • Serif: avec empattements (extensions sur les extrémités de certaines lettres)
  • Sans Serif: sans empattements
  • Monospace: avec une largeur fixe pour chaque lettre
  • Cursive: simulant une écriture manuscrite
  • Fantasy: décoratives / thématiques

Afin d'illustrer mes propos et vous donnez la famille la plus adaptée en termes d'accessibilité et de lisibilité, voici un exemple de texte avec une font de chaque famille.

Il est primordial de choisir pour vos interfaces web, une font sans-serif, elle offre une meilleure lisibilité.

Lisibilité

Mais toutes les fonts sans serif ne se valent pas non plus… Vous vous souvenez très certainement d'un jour où vous avez eu du mal à deviner le mot de passe de votre wifi, ne sachant pas si le caractère est un "i" majuscule ou un "L" minuscule. Cet aspect a son importance pour trouver la bonne font.

Il est également important d'avoir des lettres différentes et non d'un simple effet miroir pour les lettres d et b, q et p.

Avec l'image ci-dessus on se rend compte que la font "Alatsi" ne différencie pas suffisamment les caractères "1", "i"majuscule et "L" minuscule. Les lettres d et b ainsi que q et p sont symétriques.

Même chose pour la font "Josefin" mais avec une meilleure différenciation pour les 3 premiers caractères.

Enfin "Narrow" est la plus lisible des 3 avec des caractères bien différenciés.