Paramétrage du flux vertical en CSS

13 Fév 2018

Salut !

Je voudrais aborder dans cet article un point particulièrement important à mes yeux, mais souvent délaissé par les webdesigners ou les thèmes WordPress : le flux vertical des éléments dans un article (ou une simple page HTML) sans mise en page particulière.

En effet, j’ai pu observer sur la toile un paquet de mauvaises pratiques. Et comme malheureusement les ténors du thème WordPress (je ne citerai pas de noms) ne respectent pas eux-mêmes les principes élémentaires du CSS, les débutants ne risquent pas d’acquérir de bonnes bases en inspectant leur code !

Attention, je ne me considère pas comme un expert CSS, et j’ai appris tout seul grâce aux innombrables ressources de qualité sur le web. Je partage juste ma recherche sur ce sujet et évidemment ce que je vous propose ne doit pas être parfait car j’en découvre encore tous les jours. N’hésitez pas à me contredire ou à compléter cet article avec vos propres réflexions.

Voici donc pour moi les points essentiels à la mise en œuvre d’un flux vertical naturel, sain et visuellement agréable.

Avec d’abord une comparaison entre le flux standard Divi et le mien, personnalisé en CSS.

Deux textes formatés différemment

A gauche, le flux vertical standard de Divi. A droite, un flux vertical personnalisé en CSS.

Le CSS complet est à la fin de l’article 🙂

Il faut utiliser les marges pour espacer les éléments !

Eh oui, c’est quoi ce bordel ??? Je n’ai jamais compris pour quoi tout le monde mettait du padding pour séparer des paragraphes ou des titres. Peut-être parce que les gens galèrent avec les marges ?

En effet, dans le flux HTML d’un article classique sans colonne, clear, ou éléments inline, on se trouve dans une situation ou les marges se chevauchent. Concrètement, lorsqu’un élément avec une marge inférieure est suivi par un élément avec une marge supérieure, l’espace entre les deux sera la plus grande des deux marges définies. Autrement dit, les marges ne s’additionnent pas, elles se confondent, sachant que les éléments seront toujours espacés de la plus haute.

Deux blocs HTML avec des marges confondues

L’espace entre les blocs est déterminé par la marge supérieure du second.

Je pense que ce mécanisme est souvent mal compris ou tout simplement ignoré, et que la plupart des gens choisissent le padding car c’est plus « carré », plus systématique : on additionne tout et ça marche.

Mais si on travaille comme ça, cela complique finalement les choses :

  • impossible d’utiliser le padding pour définir des cadres, des fonds, des ombres, etc, pour les éléments (exemple avec le cadre ci-après) ;
  • idem pour faire varier ponctuellement les espaces sur des éléments précis ;
  • trop de combinatoire pour ajuster les espaces trop grands dus à l’addition des paddings en fonction des différents enchainements d’éléments.

Alors qu’en fait les marges simplifient tout. Par exemple, le bloc image/légende ci-dessus a tout simplement des marges de 2em, et je n’ai pas eu à me soucier de la marge du paragraphe qui le précède car étant plus petite, elle est absorbée 🙂

Bref, pour espacer des éléments, on n’utilisera désormais que les marges (à copier 500 fois avec un seul stylo par main).

Et utiliser des unités relatives pour définir les hauteurs !

En inspectant le code, je vois la plupart du temps des marges (enfin des paddings…) définies en pixels (px), donc avec une hauteur absolue. Je peux comprendre que ça paraisse plus facile pour ajuster finement un espace au départ, mais détrompez-vous. Au moindre changement de famille de police, de taille ou de hauteur de ligne, il faut tout revoir.

Pour maintenir une cohérence dans les espaces verticaux, et ce pour toutes les variations de fonte/taille/hauteur de ligne, il faut définir les marges avec les unités em ou rem (qui sont relatives) afin de toujours conserver une certaine proportionnalité avec la hauteur de la fonte du texte (pas la hauteur de la ligne, que nous verrons après).

Pour info, la différence entre les deux unités :

  • em : la hauteur est définie en fonction de la taille de la police de l’élément concerné (0.5em mesure la moitié de la taille de la fonte) ;
  • rem (« root em ») : la hauteur est définie en fonction de la taille de la police de l’élément html, le conteneur de plus haut niveau d’une page HTML (2rem mesure le double de la taille définie pour la balise html).

On en déduit que « 1em » sera différent pour chaque élément (paragraphe, titre h1, titre h2…), alors que « 1rem » sera constant dans tout le document, et ça c’est pratique !

En effet, l’utilisation de rem pour les marges permet de définir des marges indépendantes de la hauteur de chaque niveau de titre. Personnellement j’aime que les marges inférieures des titres soient constantes (mais quand même proportionnelles à la taille du texte des paragraphes).

Inversement, je positionne une marge supérieure proportionnelle à la taille du titre (en em), donc à son importance, afin de bien le séparer de ce qui précède. Ainsi le passage à un nouveau titre H2 laissera plus d’espace qu’entre deux H3.

Cas particulier de la taille du texte dans le flux vertical…

La taille du texte sur une page web pourrait faire l’objet d’un article dédié. Je souhaite juste ici exposer un principe qui me semble primordial, et qui est rarement respecté dans le monde des thèmes WordPress.

Dans l’idéal, toutes les tailles de texte (paragraphes et surtout titres) devraient toujours être définie en rem. Car il suffit alors de modifier la taille de la police de l’élément html pour que toutes les autres s’adaptent automatiquement.

De plus, pour la propriété font-size, une taille en em est proportionnelle à la taille de la fonte du conteneur parent (au contraire des paddings et marges qui dépendent de l’élément courant), donc attention à l’imbrication des div ! Un « h1 { font-size: 1.3em; } » peut vite devenir immense s’il n’est pas redéfini dans les enfants… Idem pour 0.8em qui devient vite illisible.

Toutefois, si l’on veut diminuer ponctuellement la taille d’un titre (par exemple pour les colonnes un peu serrées), alors on peut se servir de l’unité em pour le conteneur (enfant) associé à la colonne (et uniquement celui-ci pour éviter l’effet en cascade mentionné ci-dessus).

Je vous invite à lire cet article qui donne beaucoup d’informations sur la gestion de la taille du texte en em.

Et de la hauteur des lignes

La propriété line-height doit être définie en utilisant un nombre décimal sans unité et non pas en pourcentage ou en em afin de contourner ce problème d’héritage de hauteur.

Pour résumer, une hauteur de ligne en em va être calculée dans un conteneur donné par rapport à la taille de la police du texte, puis transmise aux enfants par héritage déjà calculée. Au contraire, une hauteur sans unité est interprétée comme un facteur multiplicateur, et est donc recalculée à chaque fois pour l’élément concerné, ce qui nous convient mieux.

La largeur dans le flux vertical

Jusqu’ici je n’ai parlé que de hauteur de marge, de ligne ou de texte. Mais, le flux vertical est également très influencé par la largeur du contenu. En effet, quoi de plus insipide qu’un long pavé de texte de largeur constante ? Certains vont même jusqu’à justifier leurs paragraphes… Horreur !

Désolé, moi je n’aime pas ça. En revanche, ce qui me plait, c’est de jouer sur la largeur des éléments pour varier les plaisirs et ainsi rendre la lecture plus dynamique, moins linéaire. Par exemple, insérer des images centrées qui ne prennent pas toute largeur, des listes et citations indentées (avec marge gauche et parfois droite pour aérer encore davantage), et tout ce qui pourra casser les lignes délimitées par les marges gauche et droite.

Je ne suis évidemment pas en train de dénigrer les livres imprimés. Pour moi l’exercice est différent, le support également. C’est un autre monde, alors autant se servir de tous les outils disponibles.

Attention aux derniers éléments

Il faut bien penser à supprimer la marge inférieure des derniers éléments d’un conteneur, sous peine d’avoir un espace gênant en fin de page (ou de module dans un builder). Pour ce faire, on utilise le sélecteur « :last-child », et non pas « :last-of-type » comme on trouve parfois (suivez mon regard…), sinon ça ne marche pas : par exemple, le dernier élément de type paragraphe se retrouve avec une marge nulle alors qu’il y a derrière une liste ou autre.

Idem pour les derniers éléments d’une liste, puisque de toute façon on positionne une marge après la liste elle-même.

Gérer les enchainements et les cas particuliers

Imaginons que vous vouliez paramétrer une marge spécifique avant une liste lorsqu’elle apparaît tout de suite après un titre… Comment faire en CSS ?

Il y a tout simplement un sélecteur dédié : « + ». Ainsi, « h2 + ul » permet de sélectionner toutes les listes directement précédées par un h2. Pratique, non ?

Autre exemple : j’ai positionné mes marges supérieures sur mes titres, proportionnelles aux titres, mais lorsque des titres s’enchainent directement (sans texte entre), je trouve que ces marges sont trop grandes et je préfère les rétrécir.

Aucun problème, il suffit de sélectionner les enchainements h1+h2, h2+h3, h3+h4, h4+h5 et h5+h6 et de leur attribuer la marge voulue !

Exemple de template CSS commenté

* { line-height: normal; } /* hauteur standard qui s'adapte à la fonte */

h1, h2, h3, h4, h5, h6 {
 line-height: 1.2;         /* plus joli pour les grandes tailles */
 padding-bottom: 0;        /* beurk le padding */
 margin-top: 1.3em;        /* marge supérieure proportionnelle au titre */
 margin-bottom: 1.1rem;    /* inférieure proportionnelle au paragraphe */
}
h1:first-child, h2:first-child, h3:first-child, h4:first-child, h5:first-child, h6:first-child {
 margin-top: 0;            /* pas de marge avant le premier titre */
}
h1+h2, h2+h3, h3+h4, h4+h5, h5+h6 {
 margin-top: 1.1rem;       /* marges rétrécies si les titres s'enchainent */
}
h1 { font-size: 3rem; }    /* tailles proportionnelles au paragraphe standard */
h2 { font-size: 2rem; }
h3 { font-size: 1.6rem; }
h4 { font-size: 1.3rem; }
h5 { font-size: 1.2rem; }
h6 { font-size: 1.1rem; }

p, ul, ol {
 padding-bottom: 0;        /* beurk... */
 margin-bottom: 1em;       /* marge classique */
}
p:last-child, ul:last-child, ol:last-child {
 margin-bottom: 0;         /* sauf pour le dernier */
}

ul, ol {
 margin-left: 20px;         /* on casse les lignes latérales */
 margin-right: 20px;
}

li:not(:last-child) {
 margin-bottom: 0.5em;      /* séparation des éléments */
}

blockquote {
 margin: 1.5em 30px;        /* mise en relief */
}

img {
 margin-top: 2em;           /* pour alléger un peu autour */
 margin-bottom: 2em;
}

Conclusion

Tous ces principes peuvent bien sûr être repris dans les constructeurs de page comme Divi (module texte par exemple), dans les widgets WordPress et tous types de conteneurs.

Mais souvent, en dehors des articles linéaires, la problématique n’est pas la même car on se limite à deux ou trois éléments par conteneur et on utilise plusieurs conteneurs afin de réaliser des mises en page justement moins linéaires. Et même si en théorie on peut leur appliquer le même style, dans la pratique les tailles du texte ou des marges doivent souvent être adaptées pour élaborer un design plus spécifique.

Bref, que ce soit dans un article, une page standard ou avec un page builder, cherchez toujours l’harmonie !