Pendant des années, adapter la typographie d’un site à la taille de l’écran a voulu dire multiplier les points de rupture : une taille de titre pour le mobile, une autre pour la tablette, une troisième pour le grand écran. La fonction clamp() renverse la logique — le texte grandit et rétrécit de façon continue entre une borne basse et une borne haute — mais elle introduit un piège d’accessibilité que beaucoup d’intégrations découvrent trop tard.
Le problème des tailles fixes et des paliers
Une taille fixe en pixels ignore la largeur disponible : un titre calibré pour un écran de bureau écrase la mise en page sur mobile, tandis qu’un titre pensé pour mobile paraît timide sur un moniteur large. La réponse historique — des paliers de @media — fonctionne, mais elle produit des sauts brusques à chaque seuil et une feuille de style qui gonfle à mesure que les tailles d’écran se diversifient. Entre deux paliers, la taille reste figée, alors que la largeur, elle, varie en permanence. À cela s’ajoute un coût de maintenance rarement chiffré : chaque nouvelle famille d’écrans — pliables, ultra-larges, petits mobiles — réclame un palier de plus, et la moindre refonte de l’échelle typographique oblige à rouvrir chacune des requêtes média une à une.
L’enjeu rejoint celui des échelles typographiques traitées comme des tokens de design : une valeur unique, réutilisable, qui décrit une intention plutôt qu’un chiffre figé.
clamp() : borne basse, valeur idéale, borne haute
La fonction prend trois arguments : une valeur minimale, une valeur « idéale » généralement exprimée avec une part de largeur de vue (vw), et une valeur maximale. Le navigateur choisit la valeur idéale tant qu’elle reste entre les deux bornes, et se rabat sur la borne la plus proche au-delà.
h1 {
/* jamais moins de 1.75rem, jamais plus de 3rem,
valeur idéale qui suit la largeur de vue entre les deux */
font-size: clamp(1.75rem, 1rem + 3vw, 3rem);
}Le terme central mérite attention. Un vw seul suivrait la largeur sans plancher lisible ; la part fixe en rem garantit une base qui ne disparaît jamais. La combinaison 1rem + 3vw se lit donc « une base d’un rem, à laquelle s’ajoute une pente proportionnelle à l’écran ».
Construire une échelle fluide cohérente
Plutôt que de régler chaque taille au jugé, une échelle repose sur un rapport constant entre les niveaux. Le tableau ci-dessous illustre une échelle sobre, du corps de texte au grand titre, avec des bornes qui se recoupent d’un niveau à l’autre pour éviter les inversions à largeur intermédiaire.
| Rôle | Borne basse | Terme fluide | Borne haute |
|---|---|---|---|
| Corps | 1rem | 0.95rem + 0.25vw | 1.125rem |
| Sous-titre | 1.25rem | 1rem + 1vw | 1.5rem |
| Titre de section | 1.5rem | 1rem + 2vw | 2.25rem |
| Titre principal | 1.75rem | 1rem + 3vw | 3rem |
Exprimée en variables CSS, l’échelle devient un jeu de tokens réutilisables, exactement comme une palette de couleurs :
:root {
--step-0: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
--step-1: clamp(1.25rem, 1rem + 1vw, 1.5rem);
--step-2: clamp(1.5rem, 1rem + 2vw, 2.25rem);
--step-3: clamp(1.75rem, 1rem + 3vw, 3rem);
}
body { font-size: var(--step-0); }
h2 { font-size: var(--step-2); }
h1 { font-size: var(--step-3); }L’accessibilité avant l’effet. Une taille exprimée uniquement en vw ne réagit pas au réglage de taille de police du navigateur : un internaute qui a agrandi le texte par défaut se retrouve ignoré. C’est un manquement direct au critère 1.4.4 des WCAG sur le redimensionnement du texte. La part en rem dans le terme central n’est donc pas cosmétique : elle est ce qui permet au zoom de continuer à agir.
Le piège du zoom : pourquoi mélanger rem et vw
Le point le plus mal compris de clamp() tient au comportement du zoom. Les unités de vue (vw) sont relatives à la fenêtre, pas au réglage de police : un texte dimensionné en vw pur ne grandit pas quand l’utilisateur augmente la taille de police du navigateur. En glissant une part en rem dans le terme idéal, on réintroduit une composante qui, elle, répond au zoom. La règle pratique tient en une phrase : le terme central doit toujours contenir une part en rem, jamais du vw seul.
Une taille de texte qui ne réagit plus au zoom du navigateur n’est pas fluide, elle est cassée.
Au-delà du texte : espacements et unités de conteneur
Le même principe s’étend aux marges, aux gouttières et aux rythmes verticaux, qui gagnent à respirer avec l’écran plutôt qu’à sauter par paliers. Une évolution récente affine encore l’approche : les unités relatives au conteneur (cqi, la largeur inline du conteneur) permettent à un composant de dimensionner son texte selon la place qu’il occupe réellement, et non selon la fenêtre entière. Couplées aux container queries, elles rendent un même composant lisible qu’il occupe une colonne étroite ou la pleine largeur.
.carte { container-type: inline-size; }
.carte h3 {
/* la taille suit la largeur de la carte, pas celle de la fenêtre */
font-size: clamp(1.125rem, 0.9rem + 1.5cqi, 1.5rem);
}Vérifier la fluidité avant de livrer
Une échelle fluide se contrôle sur trois gestes distincts, trop souvent confondus en un seul. Le premier est le redimensionnement de la fenêtre : il valide la pente en vw et l’absence de saut disgracieux entre les bornes. Le deuxième est le zoom du navigateur (Ctrl et +), qui doit agrandir l’ensemble de la page de façon homogène. Le troisième, le plus négligé, est le réglage de la taille de police par défaut du navigateur, poussé à 200 % : c’est lui qui révèle une taille bloquée en vw pur, restée immobile là où le reste du texte a grandi.
Une dernière précaution concerne les très grands écrans. Sans borne haute, un terme en vw continue de croître indéfiniment et finit par produire des titres démesurés au-delà de 2 500 pixels de large ; la valeur maximale de clamp() n’est donc pas un détail, c’est le garde-fou qui borne l’emballement. À l’inverse, la borne basse protège la lisibilité sur les petits écrans, où un titre trop réduit devient aussi problématique qu’un titre trop grand.
Ce qu’il faut retenir
La typographie fluide remplace des dizaines de media queries par une poignée de fonctions clamp() lisibles, à condition d’en respecter la grammaire : deux bornes qui protègent la lisibilité, un terme central qui mêle une base en rem et une pente en vw. C’est cette part en rem qui préserve le zoom et, avec lui, l’accessibilité. Passer les tailles en variables CSS transforme enfin l’échelle en un jeu de tokens maintenable, prêt à s’étendre aux espacements et aux unités de conteneur.
J’ai longtemps servi des titres en vw pur, séduit par la fluidité, jusqu’au jour où un audit d’accessibilité m’a montré que mes titres restaient de marbre quand l’utilisateur poussait la taille de police à 200 %. Depuis, je ne signe plus un seul clamp() dont le terme central ne contienne pas de rem, et je teste systématiquement mes maquettes au zoom navigateur, pas seulement au redimensionnement de fenêtre. La fluidité ne vaut rien si elle se paie en lisibilité. — Simon Janvier
Pour aller plus loin : la documentation de référence de la fonction clamp() sur MDN, avec ses cas limites et sa prise en charge navigateur.
