Garder la page immobile quand la police de la marque se charge
Ajuster les polices de secours pour que le texte ne saute plus à l'arrivée de la police de la marque, et les trois angles morts de la mesure.
Le site public compose son texte en Spline Sans, servie depuis sa propre origine. En attendant la police, le navigateur affiche le texte dans la police système qu'il a sous la main, et quand la police de la marque arrive, chaque ligne dont la largeur change se recompose et pousse la page vers le bas. Sur un téléphone lent, le haut de la page d'accueil anglaise bougeait d'un quart d'écran, et la plupart des pages juridiques en français se décalaient de cinq fois le budget de déplacement. La correction a pris quatre jours, dont la plus grande partie à obtenir une mesure qui dise la vérité.
Des polices de secours ajustées#
La correction en elle-même est classique. Le paquet de la marque déclare une @font-face de
secours par police de la marque, qui pointe vers une police système locale et ajuste sa taille et
sa hauteur de ligne pour qu'elle occupe la même place que Spline Sans. Le texte s'affiche toujours
avant l'arrivée de la police de la marque, c'est tout l'intérêt de ne pas l'attendre, et le
remplacement ne déplace plus rien.
La police de secours désigne Arial et ses équivalents métriques, ce que possèdent la plupart des visiteurs sur ordinateur. Ça a suffi pour que toutes les pages d'accueil, de services et de formulaires passent sous le budget. Cinq longues pages recomposaient encore une ligne, et le contrôle qui mesure chaque page du site construit les gardait épinglées au-dessus du budget.
Le contrôle ne voyait pas la correction#
Le contrôle charge chaque page de l'artefact de production à froid, bridé au profil mobile de
Lighthouse, et fait échouer toute page qui dépasse ses budgets de temps d'affichage, de temps de
blocage, de déplacement, d'octets et de requêtes. Il fait tourner Chromium headless sous Linux, en
CI comme en local, et aucun des deux n'a Arial. Chaque recherche local() de la police de secours
échouait, le navigateur se rabattait sur une police aux largeurs différentes, et le contrôle
mesurait un décalage qu'aucun visiteur équipé d'Arial ne verrait. La solution a été un fichier
fontconfig propre au contrôle, qui ajoute Liberation Sans, aux métriques d'Arial.
Ça n'a pas suffi, et la raison a été la plus longue à trouver. Chromium headless applique par
défaut un hinting complet des glyphes, et avec ce hinting il dessine une police locale à des tailles
en pixels entiers. L'ajustement de taille de la police de secours est d'environ 1 %, et il
disparaît dans l'arrondi : la même ligne mesurait la même largeur avec et sans lui. Quatre des cinq
pages épinglées ne se recomposaient pas du tout chez les visiteurs. Désactiver le hinting dans
fontconfig n'a rien changé ; seule l'option propre à Chromium, --font-render-hinting=none, le
fait. Lancé avec elle, le contrôle concordait avec Chrome sous Windows, avec le vrai Arial, à 0,0001
près sur dix pages.
Le troisième angle mort se trouvait dans la mesure elle-même. Le contrôle émule un téléphone tactile, et sous cette émulation Chromium marque les décalages du chargement de la page comme consécutifs à une saisie récente. La définition du cumulative layout shift de web.dev les exclut, si bien qu'un collecteur fidèle à la définition voyait chaque page parfaitement immobile alors qu'elles bougeaient de 0,05 à 0,25. Le contrôle n'envoie jamais de saisie, il compte donc tous les décalages.
Android n'a pas Arial#
Android ne possède aucune des polices que désigne la police de secours. Son texte s'affichait en Roboto, aux largeurs de Roboto, et l'accord de traitement des données en français bougeait de 0,14 dans un navigateur qui ne disposait que de Roboto. Le paquet de la marque a reçu une seconde famille de secours ajustée à Roboto, qui a ramené cette page et les autres sous le budget. Le texte à chasse fixe n'a besoin de rien : Android le résout en Droid Sans Mono, dont l'avance est de 0,6 em, comme celle de Spline Sans Mono.
Toutes les largeurs de téléphone courantes#
Le contrôle chargeait chaque page à 412 px seulement, la largeur de Lighthouse. À 360, 390 et 430 px, celles de la plupart des téléphones, des pages juridiques en français, la carte de visite et la page d'accueil française se recomposaient à l'arrivée de la police, et rien ne le mesurait. Le contrôle charge désormais chaque page aux quatre largeurs.
Une partie de ce qu'il a trouvé venait de l'ajustement lui-même. Chaque graisse avait été ajustée sur du texte courant, mais la graisse 500 partageait la police regular et tombait environ 1 % trop étroite, et les graisses grasses environ 2 % trop étroites sur les titres du site. Le paquet de la marque ajuste désormais chaque graisse sur le texte que le site compose réellement avec elle. Un détail de cet ajustement m'a surpris : l'espace de Spline Sans mesure 0,18 em contre 0,28 em pour Arial, et ajuster sur des libellés d'exemple joints par des espaces faussait le résultat d'environ 1 %. Chaque ligne d'exemple est désormais mise en forme séparément.
Le texte centré s'est révélé pire que le texte aligné à gauche. Une ligne alignée à gauche qui se recompose pousse vers le bas ce qui la suit ; une ligne centrée saute aussi latéralement, jusqu'à une demi-ligne, et le score de déplacement multiplie la surface déplacée par la plus grande distance parcourue. Sur la page française de la carte de visite, le centrage seul a triplé le score. Limiter le texte à une largeur où il se coupe de la même façon dans les deux polices l'a fait passer de 0,0442 à 0,0043.
Le plancher qu'aucun ajustement n'atteint#
Certaines recompositions ne peuvent pas être éliminées par l'ajustement. Même avec une police de secours exacte sur l'ensemble du texte, lettre par lettre les deux polices diffèrent de plusieurs pour cent dans un sens ou dans l'autre, ce qui laisse sur une ligne de téléphone un écart d'environ 1,5 %. Une ligne dont le dernier mot finit dans cette marge par rapport au bord de la colonne coupe un mot plus tôt ou plus tard quand la police arrive. Découper la police de secours en polices par groupe de lettres a ramené l'écart à environ 1 %, au prix de glyphes de tailles visiblement inégales au premier affichage, et reformuler une phrase ne fait que déplacer sa coupure vers une autre largeur.
Le budget est donc fixé par largeur. À 412 px, où toutes les mesures de référence sont prises, il reste à 0,015, soit une recomposition près du haut d'une page et rien de plus. Aux trois autres largeurs, il est de 0,25, le seuil de web.dev pour une mauvaise page : il fait échouer une page qui bouge en bloc et tolère un titre qui prend une ligne de plus, et le rapport consigne chaque largeur pour qu'une recomposition isolée reste visible.
Une recomposition qui vient de la mise en page plutôt que du texte peut encore être supprimée. Sur les pages juridiques, la version, la date et le bouton de téléchargement tenaient sur une ligne, et la question de savoir si la mention française tenait à côté de son bouton se jouait à quelques pixels. À 360 px, ça déplaçait les huit documents français de 0,05. Sur téléphone, les trois éléments s'empilent désormais.
Ce que ça a coûté#
Trois versions du paquet de la marque, dont les deux dernières ajoutent des octets à une feuille de style au budget strict : 61 octets pour la famille Roboto et 648 pour les deux nouvelles polices ajustées, chaque fois argumentés dans le registre des budgets avant que la limite ne bouge. Sur la mesure de référence du 2026-09-26, toutes les pages sauf la page à propos, dans ses deux langues, affichent leur plus grand élément vers 1,8 s, et à 412 px le plus grand déplacement restant sur une page est de 0,013.