Pourquoi les polices web sont un enjeu critique de performance
Les polices personnalisées sont partout. Elles définissent l’identité visuelle d’un site, renforcent la cohérence de marque et améliorent la lisibilité. Mais elles ont un coût : chaque fichier de police représente entre 20 Ko et 200 Ko de données supplémentaires à télécharger avant que le texte ne s’affiche correctement.
Sur un site typique utilisant deux variantes d’une police Google Fonts (regular et bold), on ajoute facilement 100 à 300 ms de délai de rendu. Sur mobile avec une connexion 3G, ce chiffre peut dépasser la seconde.
Le problème ne s’arrête pas là. Un mauvais chargement des polices impacte directement deux des trois Core Web Vitals mesurés par Google :
- LCP (Largest Contentful Paint) : si le texte principal utilise une police web, le LCP est retardé tant qu’elle n’est pas chargée.
- CLS (Cumulative Layout Shift) : le remplacement de la police de secours par la police définitive provoque des décalages de mise en page.
Autrement dit, négliger l’optimisation de vos polices web, c’est pénaliser à la fois l’expérience utilisateur et votre référencement naturel.
FOUT et FOIT : les deux symptômes d’un même problème
Avant de parler de solutions, il faut comprendre ce qui se passe concrètement dans le navigateur lorsqu’il rencontre une police web non encore téléchargée.
FOUT — Flash of Unstyled Text
Le FOUT (Flash of Unstyled Text) se produit lorsque le navigateur affiche immédiatement le texte avec une police système de secours (Arial, Times New Roman, etc.), puis le remplace par la police personnalisée une fois celle-ci chargée.
Concrètement, l’utilisateur voit :
- Le texte apparaît instantanément en Arial (ou autre fallback)
- Après 200 ms à 2 secondes, le texte “saute” et change d’apparence
- La mise en page peut se décaler si les métriques des deux polices diffèrent
C’est le comportement historique de Firefox et des anciens navigateurs. Le contenu est lisible immédiatement, mais l’expérience visuelle est dégradée par ce flash.
FOIT — Flash of Invisible Text
Le FOIT (Flash of Invisible Text) est l’approche inverse : le navigateur masque complètement le texte tant que la police personnalisée n’est pas disponible.
L’utilisateur voit :
- Un espace blanc là où le texte devrait apparaître
- Après le chargement de la police, le texte apparaît d’un coup
- Si la police échoue à charger, le texte peut rester invisible pendant 3 secondes (timeout par défaut de Chrome et Safari)
C’est le comportement par défaut de Chrome, Safari et Opera. Pendant le FOIT, l’utilisateur ne peut ni lire ni interagir avec le contenu textuel. Sur une connexion lente, c’est catastrophique.
Comparaison FOUT vs FOIT
| Critère | FOUT | FOIT |
|---|---|---|
| Texte visible immédiatement | ✅ Oui (police de secours) | ❌ Non (texte invisible) |
| Décalage visuel (CLS) | ⚠️ Oui, lors du swap | ✅ Minimal si la police charge vite |
| Impact sur le LCP | ✅ Faible (texte peint rapidement) | ❌ Fort (texte invisible = LCP retardé) |
| Expérience utilisateur | Flash gênant mais fonctionnel | Blocage de lecture potentiel |
| Navigateurs concernés | Firefox (historique) | Chrome, Safari, Opera |
Ni le FOUT ni le FOIT ne sont acceptables en l’état. La bonne nouvelle, c’est que la propriété CSS font-display permet de contrôler précisément ce comportement.
La propriété font-display : reprendre le contrôle
Introduite en 2017 et aujourd’hui supportée par plus de 97 % des navigateurs (source : Can I Use, 2024), la propriété font-display se déclare dans la règle @font-face et détermine comment le navigateur gère l’affichage du texte pendant le chargement de la police.
Syntaxe de base
@font-face {
font-family: 'MaPolice';
src: url('/fonts/mapolice.woff2') format('woff2'),
url('/fonts/mapolice.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap; /* La valeur clé */
}
Les 5 valeurs de font-display en détail
Chaque valeur correspond à une stratégie différente, avec deux phases clés :
- Période de blocage : le texte est invisible (FOIT)
- Période de swap : le texte s’affiche en fallback, puis est remplacé (FOUT)
font-display: auto
Laisse le navigateur décider. En pratique, cela signifie généralement un FOIT de 3 secondes sur Chrome. À éviter, car vous perdez tout contrôle.
font-display: block
Période de blocage courte (~3 secondes), puis swap infini. Le texte est invisible pendant le téléchargement, puis remplacé lorsque la police arrive. Utile uniquement pour les polices d’icônes où afficher un caractère de fallback serait incompréhensible.
font-display: swap
Période de blocage quasi nulle (~100 ms), swap infini. Le texte s’affiche immédiatement en police de secours, puis est remplacé dès que la police personnalisée est disponible. C’est la valeur recommandée par Google pour la plupart des cas d’usage.
font-display: fallback
Période de blocage très courte (~100 ms), swap court (~3 secondes). Si la police n’est pas chargée après 3 secondes, le navigateur conserve la police de secours pour le reste de la session. Bon compromis entre esthétique et performance.
font-display: optional
Période de blocage très courte (~100 ms), pas de swap. Le navigateur décide immédiatement s’il utilise la police personnalisée (si elle est en cache) ou reste sur le fallback. Zéro CLS garanti. C’est la valeur la plus performante, idéale pour les polices décoratives non essentielles.
Tableau récapitulatif
| Valeur | Blocage | Swap | CLS | Cas d’usage |
|---|---|---|---|---|
auto | ~3 s | Infini | Variable | À éviter |
block | ~3 s | Infini | Faible | Polices d’icônes |
swap | ~100 ms | Infini | Moyen | Texte principal, SEO |
fallback | ~100 ms | ~3 s | Faible | Bon compromis général |
optional | ~100 ms | Aucun | Nul | Polices décoratives, max performance |
Stratégie avancée : au-delà de font-display
La propriété font-display est indispensable, mais ce n’est qu’une pièce du puzzle. Chez Lueur Externe, lorsque nous auditons la performance d’un site, l’optimisation des polices fait partie d’une approche globale qui combine plusieurs techniques.
Précharger les polices critiques avec preload
Le <link rel="preload"> permet de demander au navigateur de télécharger la police en priorité haute, avant même que le parser CSS n’ait rencontré la règle @font-face :
<link rel="preload"
href="/fonts/mapolice-regular.woff2"
as="font"
type="font/woff2"
crossorigin="anonymous">
Points d’attention :
- Ne préchargez que 1 à 2 fichiers de police maximum, sinon vous retardez d’autres ressources critiques
- L’attribut
crossorigin="anonymous"est obligatoire, même pour les polices hébergées localement - Utilisez exclusivement le format WOFF2, qui offre une compression 30 % supérieure au WOFF classique
Dans nos tests internes chez Lueur Externe, le preload réduit typiquement le temps de chargement des polices de 200 à 500 ms sur les connexions mobiles moyennes.
Héberger les polices localement
Charger les polices depuis Google Fonts ou un CDN tiers semble pratique, mais cela implique :
- Une résolution DNS supplémentaire (~50–150 ms)
- Une connexion TLS supplémentaire (~100–200 ms)
- Une dépendance à un service tiers (disponibilité, latence variable)
- Des implications RGPD (transfert de l’adresse IP de l’utilisateur vers Google)
En téléchargeant les fichiers de police et en les hébergeant sur votre propre serveur, vous supprimez ces surcoûts. Voici comment convertir un import Google Fonts en hébergement local :
/* ❌ Avant : appel à Google Fonts */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
/* ✅ Après : hébergement local */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-v13-latin-regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-v13-latin-700.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
L’outil google-webfonts-helper facilite grandement cette migration en générant le CSS et les fichiers WOFF2 pour n’importe quelle police Google Fonts.
Réduire le poids avec le font subsetting
Une police complète contient souvent des milliers de glyphes : cyrillique, grec, vietnamien, symboles mathématiques… Pour un site francophone, vous n’avez besoin que du jeu de caractères latin étendu (environ 250 glyphes).
Le subsetting consiste à extraire uniquement les caractères nécessaires. Résultat :
- Police Inter Regular complète : ~96 Ko (WOFF2)
- Police Inter Regular subset latin : ~18 Ko (WOFF2)
Soit une réduction de 81 % du poids du fichier. L’outil en ligne de commande pyftsubset (du package fonttools) permet de réaliser cette opération :
pyftsubset Inter-Regular.ttf \
--output-file=Inter-Regular-latin.woff2 \
--flavor=woff2 \
--layout-features='*' \
--unicodes="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"
Optimiser la correspondance avec le fallback (size-adjust)
Le FOUT provoque des décalages de mise en page parce que la police de secours n’a pas les mêmes métriques (hauteur x, largeur des caractères) que la police personnalisée. La propriété CSS size-adjust, combinée à ascent-override, descent-override et line-gap-override, permet de calibrer le fallback pour qu’il occupe exactement le même espace :
@font-face {
font-family: 'Inter Fallback';
src: local('Arial');
size-adjust: 107.64%;
ascent-override: 90%;
descent-override: 22.43%;
line-gap-override: 0%;
}
body {
font-family: 'Inter', 'Inter Fallback', sans-serif;
}
L’outil Fallback Font Generator de Katie Hempenius calcule automatiquement ces valeurs pour n’importe quelle combinaison police web / police système. En appliquant cette technique, le CLS lié au swap de police tombe quasiment à zéro.
Cas pratique : audit et optimisation complète
Prenons un exemple concret. Un site e-commerce sous PrestaShop charge 4 variantes de la police Montserrat via Google Fonts :
- Montserrat Regular (400)
- Montserrat Medium (500)
- Montserrat Semi-Bold (600)
- Montserrat Bold (700)
Avant optimisation
- 4 fichiers WOFF2 chargés depuis
fonts.gstatic.com - Poids total : 142 Ko
- 2 requêtes DNS/TLS supplémentaires
- Aucun
font-displaydéclaré (doncauto→ FOIT de 3 s) - Aucun
preload - LCP mesuré sur mobile : 3.8 s (mauvais, seuil Google = 2.5 s)
- CLS : 0.18 (mauvais, seuil Google = 0.1)
Après optimisation
- Réduction à 2 variantes (400 et 700 suffisent dans 90 % des cas)
- Hébergement local des fichiers WOFF2
- Subsetting latin uniquement : poids total réduit à 34 Ko
font-display: swapsur les deux@font-facepreloadsur la variante Regular uniquement- Fallback calibré avec
size-adjust - LCP : 2.1 s (bon ✅)
- CLS : 0.03 (excellent ✅)
Gain total : -76 % de poids de police, -1.7 s sur le LCP, -83 % sur le CLS.
Les erreurs fréquentes à éviter
Après avoir accompagné des centaines de sites sur leur performance, l’équipe de Lueur Externe a identifié les erreurs les plus courantes liées aux polices web :
- Charger trop de variantes : chaque graisse (light, regular, medium, semi-bold, bold, extra-bold) et chaque style (normal, italic) représente un fichier supplémentaire. Limitez-vous à 2 ou 3 variantes maximum.
- Oublier font-display sur Google Fonts : si vous utilisez le service, ajoutez
&display=swapà l’URL d’import. Sans ce paramètre, aucunfont-displayn’est spécifié. - Précharger trop de polices : le preload mobilise de la bande passante. Au-delà de 2 fichiers, vous risquez de retarder des ressources plus critiques (CSS, JS principal).
- Utiliser @import au lieu de : l’instruction
@importdans un fichier CSS bloque le rendu en cascade. Préférez toujours la balise<link>dans le<head>du HTML. - Négliger le format WOFF2 : certains thèmes WordPress ou PrestaShop incluent encore des fichiers TTF ou EOT. En 2024, le WOFF2 est supporté par tous les navigateurs modernes et offre la meilleure compression.
- Ignorer les polices système : pour un blog ou un site à forte densité de texte, les polices système (
system-ui,-apple-system,Segoe UI) offrent un rendu instantané, une excellente lisibilité et un poids de… 0 Ko.
Checklist d’optimisation des polices web
Voici la liste de vérification que nous utilisons lors de nos audits de performance :
- Nombre de fichiers de police limité à 2-4 maximum
- Format WOFF2 utilisé exclusivement
-
font-display: swap(ouoptional) déclaré sur chaque@font-face - Polices hébergées localement (pas de CDN tiers)
-
preloadappliqué sur 1-2 polices critiques - Subsetting réalisé pour le jeu de caractères latin
- Police de fallback calibrée avec
size-adjust - Score LCP < 2.5 s validé dans PageSpeed Insights
- CLS < 0.1 validé dans PageSpeed Insights
- Test sur connexion 3G lente (DevTools Network Throttling)
Conclusion : la typographie au service de la performance
Les polices web ne sont pas un détail esthétique secondaire. Elles représentent souvent le troisième poste de poids d’une page web, après les images et le JavaScript, et leur impact sur le LCP et le CLS est direct et mesurable.
La bonne nouvelle, c’est que les solutions sont simples à mettre en œuvre : font-display: swap résout 80 % du problème en une seule ligne de CSS. Ajoutez le preload, l’hébergement local et le subsetting, et vous obtenez une stratégie typographique qui allie identité visuelle et performance technique.
Si vous souhaitez aller plus loin et faire auditer la performance globale de votre site — polices, images, JavaScript, cache, infrastructure serveur — les experts de Lueur Externe vous accompagnent avec des recommandations concrètes et des résultats mesurables. Depuis 2003, nous aidons les entreprises à construire des sites rapides, accessibles et bien référencés.
Contactez-nous pour un audit performance personnalisé et découvrez combien de secondes vous pouvez gagner.