CSS & rythme vertical pour le texte, les images et les tableaux
Le rythme vertical structure les lignes selon un espacement régulier de haut en
bas. Il permet de guider l’œil de manière fluide et prévisible. Grâce à l’unité
CSS rlh, ce rythme est simple à mettre en place pour le texte1. Mais
les illustrations et les tableaux peuvent perturber la mise en page. Le
typographe amateur en moi aspire à suivre la sagesse de Bringhurst :
Les titres, intertitres, citations, notes de bas de page, illustrations, légendes et autres intrusions dans le texte créent des syncopes et des variations par rapport au rythme de base d’un interlignage régulier. Ces variations peuvent et doivent animer la page, mais le texte principal doit également reprendre, après chaque variation, précisément la mesure et la phase.
― Robert Bringhurst, The Elements of Typographic Style
Pour le texte#
Trois facteurs régissent le rythme vertical : la taille de police, la hauteur de ligne et la marge ou le remplissage. Posons la base avec une police de 18 pixels et une hauteur de ligne de 1,5 :
html { font-size: 112.5%; line-height: 1.5; } h1, h2, h3, h4 { font-size: 100%; } html, body, h1, h2, h3, h4, p, blockquote, dl, dt, dd, ol, ul, li { margin: 0; padding: 0; }
Le CSS Values and Units Module Level 4 définit l’unité rlh, égale à la
hauteur de ligne de l’élément racine. Tous les navigateurs la gèrent depuis
20232. Utilisez-la pour insérer des espaces verticaux ou
corriger la hauteur de ligne quand la taille de police change3 :
h1, h2, h3, h4 { margin-top: 2rlh; margin-bottom: 1rlh; } h1 { font-size: 2.4rem; line-height: 2rlh; } h2 { font-size: 1.5rem; line-height: 1rlh; } h3 { font-size: 1.2rem; line-height: 1rlh; } p, blockquote, pre { margin-top: 1rlh; } aside { font-size: 0.875rem; line-height: 1rlh; }
Vérifions le résultat en superposant une grille4 au-dessus du texte :

rlh fonctionne bien pour régler les espaces verticaux du texte. Vous pouvez afficher la grille avec Ctrl+Shift+G.Si un sous-élément utilise une police aux métriques intrinsèques plus hautes, il peut étirer la boîte de la ligne au-delà de la hauteur configurée5. Une astuce consiste à ramener la hauteur de ligne à 1. Les glyphes débordent mais ne poussent pas la ligne plus haut.
code, kbd { line-height: 1; }
Pour les images adaptatives#
Les images adaptatives, dont la taille s’ajuste à la largeur de l’affichage,
sont difficiles à aligner sur la grille car leur hauteur nous est inconnue. Le
CSS Rhythmic Sizing Module Level 1 introduit la propriété block-step pour
ajuster la hauteur d’un élément à un multiple d’une unité de pas. Cependant, la
plupart des navigateurs ne la gèrent pas encore.
Avec JavaScript, nous pouvons ajouter un remplissage autour de l’image pour qu’elle ne perturbe pas le rythme vertical :
const targets = document.querySelectorAll(".lf-media-outer"); const adjust = (el, height) => { const rlh = parseFloat(getComputedStyle(document.documentElement).lineHeight); const padding = Math.ceil(height / rlh) * rlh - height; el.style.padding = `${padding / 2}px 0`; }; targets.forEach((el) => adjust(el, el.clientHeight));

Comme l’image est adaptative, sa hauteur peut varier. Il faut appeler la
fonction adjust() dans un observateur :
const ro = new ResizeObserver((entries) => { for (const entry of entries) { const height = entry.contentBoxSize[0].blockSize; adjust(entry.target, height); } }); for (const target of targets) { ro.observe(target); }
Pour les tableaux#
Les cellules d’un tableau pourraient fixer leur hauteur à 1rlh mais
paraîtraient à l’étroit. Passer à 2rlh gaspille trop d’espace. À la place,
nous utilisons l’interligne incrémental : une ligne sur
cinq est alignée sur la grille.
table { border-spacing: 2px 0; border-collapse: separate; th { padding: 0.4rlh 1em; } td { padding: 0.2rlh 0.5em; } }
Pour aligner les éléments après le tableau, il faut ajouter un peu de remplissage. Nous pouvons soit réutiliser le code JavaScript des images, soit utiliser quelques lignes de CSS qui comptent les lignes régulières et calculent le remplissage vertical manquant :
table:has(tbody tr:nth-child(5n):last-child) { padding-bottom: 0.2rlh; } table:has(tbody tr:nth-child(5n+1):last-child) { padding-bottom: 0.8rlh; } table:has(tbody tr:nth-child(5n+2):last-child) { padding-bottom: 0.4rlh; } table:has(tbody tr:nth-child(5n+3):last-child) { padding-bottom: 0 } table:has(tbody tr:nth-child(5n+4):last-child) { padding-bottom: 0.6rlh; }
Une cellule d’en-tête a deux fois le remplissage d’une cellule régulière. Avec
deux lignes régulières, le remplissage total vaut 2×2×0,2+2×0,4=1,6. Il faut
ajouter 0.4rlh pour atteindre 2rlh de remplissage vertical supplémentaire
autour du tableau.

Rien de tout cela n’est indispensable, mais une fois l’œil entraîné, il devient difficile de ne plus le remarquer. En attendant que les navigateurs implémentent le CSS Rhythmic Sizing, un mélange de de bidouilles CSS et d’un peu de JavaScript suffit. Le texte principal reprend désormais après chaque intrusion « précisément la mesure et la phase ». 🎼