Niveau Niveau débutant

Optimisez vos polices web

Articleweb

Publié par le , mis à jour le (10723 lectures)

performance fontes chargement webperf

Selon httparchive.org, la masse des fichiers de polices de caractère pèse en moyenne 100 ko dans une page web, soit bien plus que les poids des fichiers HTML et CSS, et autant qu'une bonne grosse image.

Autre relevé intéressant : de nos jours plus de 69% de sites web proposent de télécharger une police personnalisée. On est bien loin des antiques Arial, Verdana et Times New Roman du bon vieux temps !

Le problème est que selon les navigateurs, un fichier de fonte non chargé peut bloquer ou altérer l'affichage des contenus, ce qui est d'autant plus observable sur des terminaux mobiles.

Une ressource bloquante ?

Le processus d'affichage d'une page web dans le navigateur est tel que la page demeure blanche tant que toutes les ressources HTML, CSS (éventuellement JavaScript) ne sont pas chargées et que l'arbre du document n'est pas entièrement constitué. On parle de ressources "bloquantes".
Nous savons que d'autres types de ressources telles que les images ou vidéos sont embarquées de manière asynchrone - le navigateur les charge progressivement - et n'ont que peu d'impact sur la rapidité d'affichage.

Qu'en est-il des fichiers de polices de caractères ?

ressources bloquantes

La réponse est "ça dépend de ce qu'on appelle bloquant".

FOUT et FOIT dans la place !

Lorsqu'une fonte personnalisée est sollicitée par le navigateur, plusieurs scénarios peuvent se produire en attendant que celle-ci soit intégralement chargée. Parmi les déroulements possibles figurent les deux cas de "FOUT" et de "FOIT".

Le FOUT

Le terme "FOUT" signifie Flash Of Unstyled Text, la traduction approximative serait "flash de texte sans style" :

  • le navigateur effectue une requête de fichier de fonte personnalisée (Open Sans dans l'illustration ci-dessous)
  • en attendant que le fichier soit chargé, la police alternative est affichée immédiatement (ici Arial)
  • lorsque la police Open Sans est récupérée, elle remplace Arial

Flash Of Unstyled Text

Le FOIT

Le terme "FOIT" signifie Flash Of Invisible Text ("flash de texte invisible") :

  • le navigateur effectue une requête de fichier de fonte personnalisée (ici Open Sans)
  • en attendant que le fichier soit chargé, le contenu demeure invisible (seuls s'affichent certains artifices tels que les soulignements des liens par exemple)
  • lorsque la police Open Sans est récupérée, elle s'affiche en lieu et place de l'espace invisible.

Flash Of Invisible Text

Que font les navigateurs ?

À première vue, le comportement de FOUT semble le plus cohérent et le moins déstabilisant : qui pourrait souhaiter que les contenus soient invisibles tant que la police n'est pas chargée ?

Figurez-vous que les choses ne sont pas aussi simples qu'elles n'y paraissent. Voici par exemple : l'affichage des pictogrammes issus de polices d'icônes (font-icons), dont la plus célèbre est Font Awesome (utilisée par Bootstrap) :

fout icons

FOUT sur Alsacreations

Pour tenter de gérer au mieux ces disparités entre les types de fontes et leurs usages, chaque navigateur a adopté son comportement propre :

  • Internet Explorer affiche immédiatement la police système alternative, puis la police personnalisée dès qu'elle est chargée. C'est l'exemple typique du FOUT, pratique pour les contenus mais pas idéal pour les fontes d'icônes,
  • Safari et le navigateur natif d'Android n'affichent aucun contenu tant que la police personnalisée n'est pas chargée. Ils ont choisi le FOIT,
  • Chrome, Firefox et Opera ont adopté une démarche intermédiaire : ils n'affichent aucun contenu pendant 3 secondes maximum, puis si la police n'est toujours pas chargée se rabattent sur l'alternative, et enfin la police personnalisée s'affichera. C'est un mélange entre FOIT et FOUT.

Et les spécifications dans tout ça ? Bah, elles ne se mouillent pas trop. Leur préconisation est très officiellement  : "Les agents utilisateurs décident de leur stratégie de chargement de fontes (FOUT ou FOIT) tant que le fichier n’est pas chargé".

En partant de ce constat, tentons d'établir des stratégies pour limiter la casse.

Optimiser vos fichiers 

Choisir le bon format

Pas de suspense, oubliez vos vieux TTF et EOT : le meilleur format de police en terme de qualité-prix est WOFF2 (Web Open Font Format 2) compatible avec une majorité de navigateurs de bureau et mobiles aujourd'hui.

Prévoyez toutefois un format alternatif pour les quelques glorieux anciens. Le meilleur choix étant l'itération précédente .woff reconnue par plus de 95% des terminaux.

À titre indicatif, voici un comparatif du poids des différents formats de la police freeware Rocket Fuel :

  • rocketfuel.otf : 104 ko
  • rocketfuel.ttf : 81 ko
  • rocketfuel.woff : 55 ko
  • rocketfuel.woff2 : 43 ko

Votre déclaration @font-face idéale peut ainsi se résumer à ceci :

@font-face {
  font-family: kiwi;
  src:
    url("kiwi.woff2") format("woff2"),
    url("kiwi.woff") format("woff");
}

Elle permettra par la suite d'appliquer la fonte à vos éléments portant une classe spécifique :

.kiwi {
  font-family: kiwi, sans-serif;
}
Facile non ?

Héberger sa fonte

Contrairement à une croyance commune, il n'est pas toujours idéal de tirer profit des fournisseurs de polices tels que Google Fonts ou Typekit. Ces tierces parties ("third parties") qui hébergent les fichiers peuvent provoquer une dépendance et des ralentissements ainsi que d'autres désagréments inhérents à tous ces types de services externes.

Héberger sa fonte sur ses propres serveurs vous permet un contrôle total des fichiers, de leur disponibilité et de leur optimisation. Pour information, Alsacréations partage un projet Github "Webfonts" où il vous est possible de récupérer et héberger plusieurs dizaines de familles de polices optimisées pour le Web.

Aller plus loin avec FontSquirrel

FontSquirrel Webfont Generator est un outil en ligne gratuit bien connu des intégrateurs qui souhaitent tirer le meilleur de leur polices web.

FontSquirrel

Après avoir chargé vos fichiers de fonte, et en ayant activé le mode Expert avec tous ses superpouvoirs, vous pourrez tendre vers la perfection en terme de poids de fichier final sans altérer la qualité de votre police.

Parmi les options très intéressantes, retenez principalement :

  • subsetting : supprimez les plages de caractères non souhaitées, par exemple le cyrillique, l'hébreu ou le malaysien s'ils ne sont pas utilisées dans votre site. Vous y économiserez énormément de place.
  • x-height matching : Permet de redimensionner la police en se référant à une police système alternative (Arial, Times, Georgia, etc.). Cette fonctionnalité est un vrai bonheur en cas de FOUT car elle évite des différences trop importantes de taille, et donc les décalages ou sauts de ligne, au moment du flash entre la polices alternative et la police finale

Lorsque vous aurez fini vos réglages, FontSquirrel vous proposera de télécharger un dossier complet contenant vos différents fichiers de fonte, mais aussi une page HTML de démonstration assortie à sa feuille de style CSS et le code @font-face qu'il vous suffira d'adapter à votre projet.

Stratégies de chargement

À présent que nos fichiers de police sont optimisés dans un format parfait, intéressons-nous aux comportements de FOUT et de FOIT évoqués en début d'article.
Quoi qu'il arrive, nous allons les subir, alors tentons de nous en accommoder au mieux !

Je vous propose trois stratégies différentes, pouvant être cumulées :

  • charger ses fichiers de façon asynchrone
  • les charger dès que possible
  • les charger conditionnellement

Charger le fichier de façon asynchrone

Charger les fichiers de police via JavaScript est une façon de forcer le FOUT pour interdire le FOIT, ce que l'on peut considérer à juste titre comme étant "le moins pire des comportements". 

Le principe étant de faire croire au navigateur que seule la police alternative doit être affichée, puis dans un second temps de charger et d'afficher la police personnalisée via JavaScript. Les contenus ne seront donc jamais invisibles au chargement.

Cette technique requiert de convertir le fichier de fonte en base64 pour l'utiliser via Data-URI et le stocker dans un fichier CSS. Puis c'est JavaScript qui se missionne de charger notre fichier de "fonte-CSS" de manière asynchrone.

Exemple sommaire de fichier CSS :

@font-face {
  font-family: kiwi;
  src:
    url(data:application/font-woff;
    charset=utf-8;base64,d09GRgABAAAAANnkABMAAAABPxgAAQA…)
    format("woff");
}

Exemple sommaire de script JavaScript :

<script>
// Déclaration de loadCSS ici...
function loadCSS() { ... }
// Chargement du fichier CSS
loadCSS("data-uri.css");
</script>

<noscript><link href="data-uri.css" rel="stylesheet"></noscript>

Cet exemple tire profit de l'outil LoadCSS proposé librement par l'équipe de FilamentGroup, réputée pour ses compétences en Responsive Webdesign et en performances web.

Charger dès que possible

Si vous souhaitez éviter de recourir à JavaScript pour améliorer l'affichage de vos polices web, une autre stratégie est possible : celle d'accélérer le chargement des fichiers de fonte.

Sachez que W3C a récemment proposé la spécification rel="preload" dont les bénéfices sont parfaitement expliqués dans cet extrait de l'excellente Documentation de Mozilla :

La valeur preload de l'attribut rel pour l'élément <link> permet d'écrire des requêtes déclaratives de récupération au sein de l'élément <head>. On peut ainsi indiquer les ressources dont la page aura besoin peu après son chargement. Cela permet de les précharger au début du chargement de la page, avant que le rendu intervienne. On s'assure donc que les ressources nécessaires soient disponibles plus tôt, évitant ainsi de bloquer le rendu initial de la page et améliorant les performances.

L'attribut rel=preload n'est malheureusement pas reconnu par tous les navigateurs actuellement, mais il constitue un extraordinaire bonus pour tous les bons élèves tels que Chrome ou Firefox, et très bientôt leurs successeurs. Pourquoi ne pas faire bénéficier dès aujourd'hui vos visiteurs de ce bonus très simple à mettre en œuvre ?

Le site Shopify ne s'est pas posé la question très longtemps. Sa conclusion est sans appel et consignée dans un article élogieux (en anglais) : "Comment 17 lignes de codes ont accéléré l'affichage de Shopify de 50% ?".

Shopify et rel preload

Voici un exemple illustrant comment précharger à l'avance deux fichiers de police :

<link rel="preload" href="fonte-1.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="fonte-2.woff2" as="font" type="font/woff2" crossorigin>

Charger conditionnellement

Une autre stratégie consiste à charger conditionnellement les fichiers de police, ou plus exactement de ne pas les solliciter sur un périphérique mobile par exemple pour des raisons de performance.

L'objectif est de proposer par défaut une police système et de lier la police personnalisée à l'aide de CSS Media Queries en se basant sur une taille d'écran par exemple.

Concrètement, c'est très simple à mettre en place. Pour commencer, sachez que la déclaration @font-face n'impose pas le chargement de la ressource, celle-ci ne sera chargée que lorsqu'elle sera explicitement demandée en l'appliquant sur un élément de la page.

Dans la pratique, il suffit de procéder ainsi pour ne charger et afficher la fonte "kiwi" que lorsque l'écran est supérieur à 576px :

body {
  font-family: arial,sans-serif;
}
@media (min-width: 576px) {
  body {
    font-family: kiwi, arial, sans-serif;
  }
}

Cette méthode est très bénéfique en terme de performances mais n'est bien entendu pas idéale car il faut :

  • accepter que la police soit différente entre la version mobile et la version de bureau
  • assumer qu'un mobile est défini par sa taille d'écran, ce qui est forcément approximatif

À ce propos, sachez que de plus en plus de sites web (Booking, Medium, WordPress, GitHub, Alsacréations, entre autre) ont cessé de tenter d'imposer une police identique à tous leurs visiteurs, même lorsqu'il s'agit d'une police classique : plutôt que de proposer Arial, Verdana ou Times, ils ont opté pour une police variable adaptée à chaque système d'exploitation :

body {
  font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
}

Cette famille de fontes, appelée "System Font Stack" propose à chaque utilisateur sa police habituelle sur son OS : sur Windows ce sera "Segoe UI" ou "Tahoma" pour les plus anciens, sur Android ce sera "Roboto", etc. Ainsi vos visiteurs ne seront pas surpris par vos choix typographiques et se sentiront comme chez eux dans vos pages de contenus.

Le site Booking.com explique son choix (en anglais) : "Implementing system fonts on Booking.com — A lesson learned.".

Ne plus subir le FOUT / FOIT ? 

Dans un avenir plus ou moins proche, différents moyens permettront de ne plus subir les comportements indésirables de FOUT et de FOIT lorsque les polices seront en transit vers nos navigateurs.

Une spécification officielle, la Font Loading API, est prévue dans les bacs, et un émulateur FontFaceObserver est déjà utilisable en production. 

Font Loading API

La spécification CSS Font Loading Module Level 3 est encore à l'état de brouillon mais n'en demeure pas moins supportée par une très large part des navigateurs récents.

Ce module prévoit une interface de script permettant de gérer très finement les étapes du chargement des fichiers de police et le comportement a adopter pour le navigateur au cas par cas.

var f = new FontFace("newfont", "url(newfont.woff)", {});
f.load().then(function (loadedFace) {
  document.fonts.add(loadedFace);
  document.body.style.fontFamily = "newfont, serif";
});
document.fonts.ready().then(function() {
  // Toutes les familles @font-face sont prêtes
});

FontFaceObserver

FontFaceObserver est un script de "polyfill" réalisé par Bram Stein et permettant d'émuler Font Loading API pour les navigateurs qui ne reconnaissent pas encore la spécification.  Sa mise en oeuvre est assez simple.

Partie JavaScript :

// include fontFaceObserver here...
new w.FontFaceObserver( "Source Sans Pro" )
.check()
.then( function(){
  w.document.documentElement.className += " fonts-loaded";
});

Partie CSS :

body {
  font-family: sans-serif;
}
.fonts-loaded body {
  font-family: "Source Sans Pro", sans-serif;
}

Ceci permet un chargement asynchrone du fichier, puis une fois que celui-ci est prêt à être utilisé, l'ajout d'une classe à l'élément racine <html> pour appliquer les propriétés de police sur l'ensemble du document.

Bonus : font-display

Vous connaissez la propriété CSS font-display ? Rassurez-vous, vous n'êtes pas seul·e. En effet, cette nouveauté n'est encore qu'à l'état de proposition non officielle, c'est à dire qu'elle n'a même pas encore atteint le stade de brouillon au W3C.

Toujours est-il que cette propriété a la bonne idée de réaliser exactement notre fantasme, c'est à dire de pouvoir décider quel sera le comportement des navigateurs lors du chargement de nos fontes.

Par exemple, il est possible d'imposer un FOUT c'est à dire d'afficher immédiatement la police alternative avec la valeur swap :

@font-face {
  font-family: kiwi;
  src: ...;
  font-display: swap;
}

Le support des navigateurs, sans surprise, est quasi nul aujourd'hui : Chrome vient tout juste de l'implémenter et il est probable que d'autres vont suivre. En tout cas, rien ne vous empêche de l'ajouter en bonus, vous ne casserez pas le Web. 
Vous trouverez de plus amples informations sur cette fonctionnalité sur le site de Zach Leatherman.

Bonus : variable fonts

Autre domaine à surveiller de près (merci à ThomasLinard pour son commentaire avisé) : celui des "Variable Fonts".

variable font

Sans entrer dans les détails, disons que les variable fonts ont fait leur entrée dans CSS Fonts Module Level 4 et consistent en un format de fonte qui intègre en un seul fichier toutes les graisses et autres variations de familles de police. Ainsi, plutôt que de devoir charger un fichier pour la version classique, un autre pour la version grasse, un autre pour l'italique, etc. tout sera réuni en un seul fichier. C'est bien évidemment une bénédiction pour les performances web.

Je vous invite à lire l'article "What do Variable Fonts mean for Web Developers?" qui explique très bien le point de vue d'un développeur à ce sujet.

Conclusion

Dans le domaine de la performance tout autant que celui de l'esthétique et de l'ergonomie, le choix de vos polices web relève d'une importance cruciale. De leur nombre et de leur poids dépendront la rapidité d'affichage de vos contenus et la qualité d'expérience de vos utilisateurs.

Ne faites pas comme le site de vanityfair.fr qui importait près de 450 ko de fichiers de fontes à une époque. Ne cédez pas à la tentation d'imposer de multiples chargements juste parce que "ces 8 polices sont troooop classes". Faites des choix. Optimisez. Optez pour des stratégies de chargement. Tous vos visiteurs, sans exception, vous en remercieront.

Commentaires

Bonjour Raphaël,

Merci pour cet article très complet ! Toutefois, quelques remarques :

* Sur votre projet Github "Webfonts" : c'est sans doute utile, mais il faudrait préciser qu'il s'agit de vieilles versions des fontes. Ça a des avantages et des inconvénients. Par exemple, la Montserrat a été refaite par sa créatrice Julieta Ulanovsky en une version à neuf graisses (+ italique), avec une progression régulière entre les graisses, une plus grand plage de caractères (et donc un plus grand support linguistique), et plein de problèmes techniques corrigés. C'est la version actuellement disponible sur l'API Google Fonts et téléchargeable aussi sur son GitHub : https://github.com/JulietaUla/Montserrat

Alors ça change (les deux graisses d'origine ne se retrouvent pas exactement au même endroit dans une version à neuf graisses et progression "lissée") et le crénage a été revu (ce qui est une bonne chose, mais ça fait "bouger" le texte), mais pour commencer un nouveau site, la nouvelle version est nettement supérieure.

* Les Variable Fonts: vu qu'on parle du poids des fontes, un petit mot pour prévenir que la technologie VF arrive et qu'on fait déjà des choses impressionnantes avec aurait été bien. Je conseille https://blog.prototypr.io/what-does-variable-fonts-mean-for-web-developers-2e2b96c66497

@ThomasLinard : Bonjour et merci pour votre retour constructif :)

* Projet Github : vous avez raison, mais c'est le principe de Github : si quelqu'un (vous ?) se sent concerné pour faire avancer le projet, il est parfaitement envisageable de participer et de mettre à jour les fontes.

* Variable Fonts : je n'y avais pas pensé, bien vu. Je rajouterai un bonus dès que possible. Ceci dit, les VF mériteraient un article à part entière... encore une fois, je fais appel aux bonnes âmes dans le coin :p

Ah, tiens, pas d'emoji ? Le champ n'est pas en UTF-8 ?

Bon, je reprends :

@Raphael : parfois une remarque en commentaire est une information suffisante (je l'espère du moins, désolé de ne pas proposer plus).

Merci pour l'article.

J'utilise plutôt le webfontloader de typekit parce qu'il se charge de façon asynchrone et l'utilisation des librairies externe est facilité. Je vais lire l'article de dareboost et peut être changer ça.

https://github.com/typekit/webfontloader

Dans font-face, j'ai découvert récemment que l'on peut utiliser l'attribut "local" pour vérifier si la police est déjà installé sur la machine avant de charger les fichiers. Par exemple, le font-face de google pour la roboto slab est :

@font-face {

font-family: 'Roboto Slab';

font-style: normal;

font-weight: 400;

src: local('Roboto Slab Regular'), local('RobotoSlab-Regular'), url(http://fonts.gstatic.com/s/robotoslab/v6/y7lebkjgREBJK96VQi37ZiYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2');

}

Enfin, parce que ça me saoule d'écrire une déclaration font-face (qui diminue avec le temp c'est vrai ^^), j'ai créé un mixin sass.

Pour ceux que ça intéresse : https://codepen.io/davidpollet/pen/ORyYap

Merci pour votre article mais j'ai une question au sujet du point

"Contrairement à une croyance commune, il n'est pas toujours idéal de tirer profit des fournisseurs de polices tels que Google Fonts ou Typekit. Ces tierces parties ("third parties") qui hébergent les fichiers peuvent provoquer une dépendance et des ralentissements ainsi que d'autres désagréments inhérents à tous ces types de services externes."

Car si effectivement la recommandations je suis toujours surpris par celle-ci.

Si effectivement c'est un dépendance, c'est un dépendance à google. Et bien que je ne suis pas particulièrement désireux d'être dépendant de google, je ne crains pas trop celle-ci. Car en toute honneté les serveurs googleapi on de meilleurs perf et dispo que mon serveur. Alors les fois ou mes visiteurs sont géné en raison d'indisponibilité ou ralentissement inhérents à google me parait anecdotique.

En revanche, je vois un avantage à savoir la paraléllisation. Car à moins d'être en http/2 la paraléllisation est limité à 5 ressource par domaine. Donc augmenter le nombre de domaine est un gain en perf. non?

Ai je raté ou mal saisit quelque chose?

@gotcha5832 : Hello,

En fait, outre le fait qu'il s'agisse d'un service qu'on ne maîtrise pas, il y a deux inconvénients majeurs à utiliser des fontes hébergées chez Google :

1- Google s'amuse parfois à modifier, ajouter, et pire supprimer certaines fontes de son catalogue (sans prévenir bien sûr)

2- j'avais lu quelque part que - réparti dans l'année - les serveurs de Google Font était indisponible 5min par jour en moyenne.

Concernant la parallélisation, c'est une bonne pratique sur desktop en effet, mais rarement sur mobile où la bande passante est souvent plus faible et où le goulot d'étranglement est rapidement comblé si plusieurs ressources sont chargées en même temps.

@Raphael

Merci pour tes réponses, c'est top d'avoir des réponses clair, détaillé et fiable

1- Des modif j'en ai vu, mais des suppression pas encore, mais merci, du coup ca me refroidit

2- Ah ouai

Concernant la parallélisation, j'ai du coup un question qui est limite hors sujet mais j'espère avoir ton avis

Pour le Js, j'ai tendance à récupérer jquery sur le googleapi (src="https://ajax.googleapis.com/ajax/libs/jquery/…) plutot que de l'intégrer à un gros fichier minifié sur mon serveur pensant que

- Avec un peu de chance le visiteur l'a déjà en cache navigateur ayant déja parcouru un site utilisant ce fichier, et ne vas pas le re-télécharger

- Jouer sur le parallélisme.

Que penses tu de ce raisonnement?

Article super intéressant ! Merci @Raphael.

Comme l'a dit @davidpollet un peu plus haut, j'ai également retenu d'une intervention de @iamhiwelo lors de la kiwiparty 2015 l'utilisation de local() au cas ou la font était déjà chargée.

Et je ne crois pas avoir déjà vu le lien (ou alors j'ai lu trop vite) mais voila un petit tableau des font native sur chaque device http://jordanm.co.uk/tinytype/ (donné également par @iamhiwelo lors de sa prez)

Bonne journée !

Bonjour,

Merci pour cet article très intéressant.

Une question à propos de l'utilisation des Google webfont. Service gratuit donc sait-on si Google ne se "paye" pas en collectant, comme à son habitude, des informations sur le site voire ses visiteurs ? C'est quand même la base de son modèle économique…

Merci.

Commenter

Vous devez être inscrit et identifié pour utiliser cette fonction.

Connectez-vous (déjà inscrit)

Oubli de mot de passe ? Pas de panique, on va le retrouver

Pas encore inscrit ? C'est très simple et gratuit.