Mettre en forme le texte en CSS : police, taille, interligne

Mettre en forme du texte, c'est souvent la première vraie satisfaction quand on apprend le CSS : on change une ligne, et toute la page devient plus agréable à lire. Quand j'ai démarré ma reconversion en 2017, le soir et le week-end, c'est exactement par là que je suis passé. Dans cet article, je reprends les propriétés essentielles (police, taille, interligne, graisse, alignement) avec les pratiques actuelles : polices système, unité rem, line-height sans unité et taille fluide avec clamp().

Toutes les valeurs annoncées ici ont été mesurées dans Chrome pendant la rédaction, avec getComputedStyle(). Vous n'aurez donc pas à me croire sur parole. Si vous découvrez tout juste les feuilles de style, commencez par l'article sur comment donner du style à une page grâce au CSS, puis revenez ici.

Avant de commencer : les variables CSS (custom properties)

Avant d'attaquer les propriétés de texte, je vous présente un outil qui va nous servir tout du long : les variables CSS, officiellement appelées custom properties. Une variable CSS se déclare avec un nom qui commence par deux tirets, en général sur le sélecteur :root (la racine du document), et se lit avec la fonction var() :

:root {
  --police-texte: system-ui, sans-serif;
  --taille-texte: 1rem;
  --interligne: 1.6;
}

p {
  font-family: var(--police-texte);
  font-size: var(--taille-texte);
  line-height: var(--interligne);
}

L'intérêt est énorme pour la mise en forme du texte : vous définissez la taille, la police et l'interligne une seule fois, et tout le site les réutilise. Le jour où vous changez d'avis, vous modifiez une ligne au lieu de cinquante. J'ai vérifié dans le navigateur pendant la rédaction : avec la feuille de style ci-dessus, un paragraphe se retrouve bien avec une taille calculée de 16 px et un interligne de 25,6 px (soit 1,6 fois 16 px). Les variables sont donc résolues exactement comme si vous aviez écrit les valeurs à la main.

font-family : misez sur les polices système

La propriété font-family définit la police du texte. On lui donne une liste de polices séparées par des virgules, du choix préféré au choix de secours : le navigateur essaie la première, et passe à la suivante s'il ne la trouve pas sur la machine du visiteur. C'est ce qu'on appelle une pile de polices (font stack). La liste doit toujours se terminer par une famille générique : serif (avec empattements), sans-serif (sans empattements), monospace (chasse fixe, pour le code), cursive ou fantasy.

À l'époque où j'ai appris, on recommandait des listes de polices « web safe » du type Arial, Verdana ou Georgia. Aujourd'hui, la pratique la plus courante pour du texte courant est la pile système : on demande au navigateur d'utiliser la police d'interface du système d'exploitation du visiteur. C'est gratuit, immédiat (aucun fichier à télécharger) et le rendu paraît natif sur chaque plateforme :

body {
  font-family: system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

Le mot-clé system-ui désigne directement la police du système (Segoe UI sous Windows, San Francisco sous macOS, Roboto sous Android). Les noms suivants servent de secours pour les navigateurs plus anciens, et sans-serif ferme la marche. Retenez aussi que les noms de police composés de plusieurs mots s'écrivent entre guillemets, comme "Segoe UI".

font-size : adoptez le rem

La propriété font-size règle la taille du texte. La question qui fâche, c'est l'unité. Le pixel (px) semble le plus simple, mais il a un défaut sérieux : une taille figée en pixels ignore le réglage « taille de police » que l'utilisateur peut définir dans les préférences de son navigateur. Pour respecter ce choix, on utilise le rem (root em) : 1 rem vaut la taille de police de l'élément racine, soit 16 px dans la configuration par défaut. Mesuré dans Chrome pendant la rédaction : 1rem donne une taille calculée de 16 px, et 1.25rem donne 20 px.

p {
  font-size: 1rem;
} /* 16 px mesuré */
h2 {
  font-size: 1.5rem;
} /* 24 px */
small {
  font-size: 0.875rem;
} /* 14 px */

Notez au passage que les décimales s'écrivent avec un point, jamais avec une virgule : 1.5rem et non 1,5rem.

Et l'unité em, alors ?

L'unité em existe toujours, mais elle est relative à la taille de l'élément parent, pas à la racine. Conséquence : les valeurs se multiplient à chaque niveau d'imbrication. J'ai fait le test dans le navigateur avec trois blocs imbriqués portant chacun font-size: 1.2em : le premier niveau affiche 19,2 px, le deuxième 23,04 px et le troisième 27,65 px. La taille dérive toute seule, sans que personne l'ait demandé. Avec 1.2rem, les trois niveaux restent sagement à 19,2 px. C'est la raison pour laquelle je vous conseille le rem pour les tailles de texte, et de réserver l'em aux cas où l'on veut justement une valeur proportionnelle au parent (un padding de bouton, par exemple).

font-size: 1.2em (cumul) niveau 1 : 19,2 px niveau 2 : 23,04 px niveau 3 : 27,65 px font-size: 1.2rem (stable) niveau 1 : 19,2 px niveau 2 : 19,2 px niveau 3 : 19,2 px
Trois blocs imbriqués avec la même règle : em se cumule à chaque niveau, rem reste stable (valeurs mesurées dans Chrome).

clamp() : une taille de texte fluide

Pour les titres, une taille unique est rarement idéale : ce qui est confortable sur un grand écran devient énorme sur un téléphone. La fonction clamp() résout ce problème en une ligne. Elle prend trois valeurs : un minimum, une valeur idéale (souvent un calcul mêlant rem et vw, l'unité qui vaut 1 % de la largeur de la fenêtre) et un maximum.

h2 {
  font-size: clamp(1.125rem, 1rem + 1.5vw, 2rem);
}

J'ai mesuré cette règle dans Chrome à plusieurs largeurs de fenêtre pendant la rédaction. Sur un écran de 390 px de large (un mobile courant), le titre fait 21,85 px, soit exactement 16 px + 1,5 % de 390 px. Sur un écran de 1280 px, le calcul donnerait 35,2 px, mais le plafond de 2rem entre en jeu : la taille mesurée est de 32 px. À 2200 px, elle reste à 32 px. Entre les deux bornes, la taille glisse en continu avec la largeur de la fenêtre, sans aucune media query.

largeur de la fenêtre taille du texte 390 px de large : 21,85 px mesuré 1280 px : 32 px (plafond) min 1.125rem zone fluide : 1rem + 1.5vw max 2rem
Comportement mesuré de clamp(1.125rem, 1rem + 1.5vw, 2rem) : la taille suit la largeur de la fenêtre entre un plancher et un plafond.

line-height : l'interligne, toujours sans unité

La propriété line-height règle la hauteur des lignes, donc l'aération du texte. Pour du texte courant, une valeur entre 1.5 et 1.6 est un bon point de départ. Le point important, et c'est un piège classique, est de l'écrire sans unité :

body {
  line-height: 1.5;
}

Pourquoi sans unité ? Parce que l'héritage ne fonctionne pas pareil. Une valeur sans unité est transmise aux enfants comme un facteur : chaque élément recalcule son interligne à partir de sa propre taille de police. Une valeur en pourcentage ou en em, elle, est calculée une fois chez le parent, puis transmise figée. J'ai mesuré la différence dans le navigateur : avec un parent en 16 px et line-height: 1.5, un titre enfant de 32 px obtient un interligne de 48 px, ce qui est correct. Avec line-height: 150% sur le même parent, le même titre hérite d'un interligne figé à 24 px, plus petit que sa propre police : les lignes se chevauchent. Même valeur en apparence, résultat opposé.

font-weight : la graisse du texte

La propriété font-weight contrôle la graisse (l'épaisseur du trait). Les mots-clés normal et bold existent toujours, mais la propriété accepte en réalité toute l'échelle numérique de 100 à 900. Mesuré dans Chrome : normal correspond à une graisse calculée de 400, bold à 700, et une valeur intermédiaire comme 600 (demi-gras) est bien conservée telle quelle.

strong {
  font-weight: 700;
} /* équivalent de bold */
.demi-gras {
  font-weight: 600;
}

Attention tout de même : la graisse demandée ne s'affichera fidèlement que si la police fournit ce niveau. Une police classique ne propose souvent que deux graisses (normale et grasse), tandis que les polices variables couvrent l'échelle entière. Avec une pile système comme celle vue plus haut, les niveaux courants (400, 600, 700) sont disponibles sur les systèmes récents.

font-style et text-decoration : italique, souligné, barré

Deux propriétés complètent la panoplie. font-style passe le texte en italique avec la valeur italic (et normal pour l'annuler). text-decoration gère les lignes décoratives : underline pour souligner, line-through pour barrer, overline pour une ligne au-dessus, none pour tout retirer. La vieille valeur blink (texte clignotant) a disparu : les navigateurs actuels l'ignorent, et c'est tant mieux pour vos yeux.

em {
  font-style: italic;
}
a {
  text-decoration: underline;
}
.ancien-prix {
  text-decoration: line-through;
}

Gardez en tête que le CSS gère l'apparence, pas le sens. Pour indiquer qu'un mot est important, on utilise d'abord les balises HTML de structuration du texte comme <strong> et <em>, puis le CSS ajuste leur rendu si besoin.

text-align : l'alignement du texte

Enfin, la propriété text-align aligne le texte à l'intérieur de son bloc. Quatre valeurs couvrent l'essentiel des besoins :

h2 {
  text-align: center;
}

À retenir

Voici la feuille de route que j'aurais aimé avoir à mes débuts :

Avec ces propriétés, vous savez déjà rendre un texte propre et confortable à lire sur tous les écrans. La suite logique, c'est de travailler l'ambiance de la page : direction les couleurs et les fonds en CSS. Bonne mise en forme, Sam.