Alignement en CSS, un guide complet
Tout sur l'alignement en CSS par Rachel Andrew. Les choses ont beaucoup évolué dernièrement avec Flexbox, CSS Grid et la spécification Box Alignment. Dans la continuité de ses articles de référence déjà traduits dans la Cascade.
Il existe aujourd'hui bien des façons d'aligner les choses en CSS et il n'est pas toujours évident de faire un choix. Connaître les options qui s'offrent à nous est encore la meilleure façon de concevoir les solutions optimales pour résoudre un problème.
Dans cet article, je vais passer en revue les différentes méthodes d'alignement qui existent aujourd'hui. Mais plutôt que de donner un mode d'emploi pour chacune, je vais examiner les points d'achoppement que l'on peut rencontrer et je renverrai à des articles de référence plus détaillés si vous souhaitez approfondir le sujet. Comme souvent en CSS, le plus important est de comprendre les fondamentaux des méthodes, le reste est affaire de détails.
Alignement du texte et des éléments inline
Quand on a du texte et autres éléments inline dans une page, chaque ligne de contenu est traitée comme une boîte de ligne (line-box). La propriété text-align
alignera ce contenu dans la page — par exemple si vous voulez centrer votre texte ou le justifier. Mais parfois vous voudrez aligner les choses à l'intérieur de cette boîte de ligne par rapport à d'autres choses, par exemple si vous avez une icône affichée à côté du texte, ou bien des textes de taille différente ( NdT : si vous avez besoin de rafraîchir vos connaissances sur inline et block, l'article CSS Block, Inline et Inline-Block remettra tout en place !).
Dans l'exemple ci-dessous, j'ai mis un bout de texte à côté d'une image inline. J'utilise vertical-align: middle
sur l'image pour aligner le texte par rapport au milieu de l'image ( NdT : pour modifier les valeurs, cliquez sur "Edit on CodePen").
La propriété line-height et l'alignement
La propriété line-height
modifie la dimension de la boîte de ligne et peut donc avoir des conséquences sur l'alignement. L'exemple qui suit utilise une valeur élevée de hauteur de ligne (150 px) et j'ai aligné l'image sur top
. L'image est donc alignée sur le haut de la boîte de ligne et non sur le haut du texte. Si vous supprimez cette line-height
, ou si vous lui donnez une valeur inférieure à la dimension de l'image, alors l'image et le texte s'aligneront sur le haut du texte.
La propriété line-height
et la gestion de la taille du texte sont en réalité assez compliquées, je ne vais pas me lancer dans ce sujet ici, mais si vous souhaitez aligner précisément les éléments inline et si vous souhaitez comprendre le détail de ce qui se passe, je vous recommande la lecture de CSS avancé : métrique des fontes, line height et vertical align par Vincent de Oliveira.
Quand utiliser la propriété vertical-align ?
La propriété vertical-align
est utile pour aligner les éléments inline. Cela comprend aussi les éléments affichés avec display: inline-block
. Le contenu des cellules de tableaux peut également être aligné avec cette propriété.
La propriété vertical-align
n'a aucun effet sur les items flex ou grid et par conséquent si elle est utilisée dans le cadre d'une stratégie de solution de rechange (fallback), elle cessera d'être effective dès lors que l'élément parent sera transformé en conteneur flex ou grid. Par exemple, dans l'exemple ci-dessous, j'ai un ensemble d'items alignés via display: inline-block
ce qui signifie que j'ai la possibilité d'aligner les items même si mon navigateur n'est pas compatible avec Flexbox.
Dans l'exemple suivant, j'ai traité l'inline-block
comme un fallback de Flexbox. Les propriétés d'alignement ne s'appliquent plus et je peux ajouter align-items
pour aligner mes items dans Flexbox. Vous pouvez remarquer que c'est bien la méthode Flexbox qui aligne mes items parce que les gouttières qui les séparent dans la vue précédente ont disparu.
C'est parce que vertical-align
marche avec les cellules de tableaux que le "truc" permettant de centrer verticalement un item via display: table-cell
fonctionne.
Maintenant que nous avons de meilleures méthodes pour aligner les boîtes en CSS (comme nous allons le voir tout de suite), nous n'avons plus besoin de recourir aux propriétés vertical-align
et text-align
ailleurs que là où elles remplissent leur fonction initiale, à savoir avec les éléments inline et textuels. Sur ces formats, elles demeurent parfaitement valides — par conséquent si vous souhaitez aligner des éléments inline ce sont elles, et non l'alignement de boîte, qu'il convient d'utiliser.
Alignement de boîte
La spécification Box Alignment s'intéresse à tout le reste. La spécification détaille les propriétés d'alignement suivantes :
- justify-content
- align-content
- justify-self
- align-self
- justify-items
- align-items
Peut-être pensez-vous que ces propriétés font partie de la spécification Flexbox, voire Grid. À l'origine, c'est là qu'elles sont nées en effet et d'ailleurs elles existent encore dans la spécification de niveau 1 Flexbox. Cependant, elles ont été déplacées dans une spécification séparée lorsqu'il est apparu qu'elles avaient une portée plus générale. Nous les utilisons maintenant aussi avec CSS Grid Layout et elles sont spécifiées pour d'autres méthodes de mise en page, même si les navigateurs actuels ne sont pas encore compatibles.
Par conséquent, la prochaine fois que quelqu'un sur Internet vous dira que l'alignement vertical est la chose la plus difficile qui soit en CSS, vous pourrez lui répondre ceci (ça tient même dans un tweet) :
.container {
display: flex;
align-items: center;
justify-content: center;
}
Dans le futur il est même possible qu'on puisse se dispenser de display: flex
, une fois les propriétés Box Alignment implémentées pour Block Layout. Pour l'instant en tout cas, il est toujours nécessaire de faire du parent un conteneur flex si l'on veut aligner verticalement et horizontalement.
Les deux sortes d'alignement
Quand on aligne des items flex ou grid, on a en fait deux choses à aligner :
- On a de l'espace libre dans notre container flex ou dans notre grille (une fois les éléments ou les pistes affichées).
- On a l'élément lui-même à l'intérieur de la surface grid, ou sur l'axe transversal dans le conteneur flex.
Je vous ai montré quelques propriétés précédemment, toutes ces propriétés d'alignement peuvent être vues comme appartenant à deux groupes. Celles qui s'occupent de la distribution de l'espace libre et celles qui alignent l'élément lui-même.
Gestion de l'espace libre : align-content et justify-content
Les propriétés dont le nom se termine par -content
ont pour objet la distribution de l'espace. Lorsque vous utilisez align-content
ou justify-content
, vous répartissez l'espace disponible entre les pistes de grilles (grid tracks) ou entre les items flex. Ces propriétés ne modifient pas les dimensions des items flex ou grid, mais déplacent les items en fonction de l'espace disponible.
Ci-dessous nous avons deux exemples, un flex et un grid. Tous deux ont un conteneur plus grand que nécessaire, par conséquent je peux utiliser align-content
et justify-content
pour répartir cet espace.
Déplacement des items : justify-self, align-self, justify-items et align-items
Et puis nous avons align-self
et justify-self
qui s'appliquent à des items flex ou grid individuels. On peut également utiliser align-items
et justify-items
sur le conteneur pour appliquer toutes les propriétés en une fois. Ces propriétés s'appliquent à l'item flex ou grid, en déplaçant le contenu à l'intérieur de la zone grid ou de la ligne flex.
- Grid Layout : les deux propriétés sont disponibles, vous pouvez déplacer l'item sur les axes block et inline.
- Flex Layout : on peut seulement aligner le long de l'axe perpendiculaire car l'axe principal n'est contrôlé qu'au niveau de la répartition de l'espace. Donc si vos items sont sur une rangée, vous pouvez utiliser
align-self
pour les déplacer verticalement à l'intérieur de la ligne.
Dans l'exemple qui suit, j'ai un conteneur flex et un conteneur grid et j'utilise align-items
et align-self
dans Flexbox pour déplacer les items vers le haut ou le bas le long de l'axe perpendiculaire (cross axis). Si vous utilisez Firefox et que vous inspectez l'élément avec l'Inspecteur de Flexbox, vous verrez la dimension du conteneur flex ainsi que la façon dont les items sont déplacés verticalement à l'intérieur.
Dans Grid, je peux utiliser les quatre propriétés pour déplacer les items à l'intérieur de leur zone de grille. Là encore, l'Inspecteur Grid de Firefox vous aidera à jouer avec les alignements. Avec les lignes en filigrane, on voit clairement la zone dans laquelle le contenu est déplacé :
Cliquez sur Edit on Codepen pour modifier les valeurs :
align et justify vous paraissent encore confus ?
Parmi les problèmes souvent mentionnés concernant les propriétés d'alignement de Grid et Flexbox, il y a la difficulté à se rappeler laquelle utiliser : aligner ou justifier ? quelle direction correspond à chacune ?
Pour Grid Layout, vous devez savoir si vous alignez dans la direction Block ou Inline. Cela dépend de votre mode d'écriture : pour le français, la direction Block correspond à l'empilement des blocs, c'est donc la direction verticale. La direction Inline correspond au sens de l'écriture, c'est donc (en français du moins) de gauche à droite horizontalement.
Pour aligner dans la direction Block, vous utiliserez les propriétés commençant par align-
. Vous utiliserez align-content
pour répartir l'espace entre les pistes de grille, s'il y a de l'espace libre à l'intérieur de votre conteneur grid, et vous utiliserez align-items
ou align-self
pour déplacer un item à l'intérieur de la zone de grille où il se trouve.
Dans l'exemple suivant, nous avons deux mises en page grid. L'une a un writing-mode: horizontal-tb
(le mode par défaut pour le français) et l'autre un writing-mode: vertical-rl
. C'est la seule différence entre les deux. Vous voyez que les propriétés d'alignement appliquées fonctionnent exactement de la même façon sur l'axe block dans les deux modes.
Pour aligner dans la direction inline, utilisez les propriétés commençant par justify-
. Utilisez justify-content
pour répartir l'espace entre les pistes de grille et justify-items
ou justify-self
pour aligner les items à l'intérieur de leur zone de grille dans la direction inline.
Là encore, j'ai deux exemples de mise en page grid pour vous montrer qu'un inline est toujours un inline, quel que soit le mode d'écriture.
Avec Flexbox, c'est un peu plus compliqué car nous avons un axe principal (main axis) qui peut être changé en row
ou en column
. Alors occupons-nous d'abord de cet axe principal. Il est déterminé avec la propriété flex-direction
. La valeur par défaut est row
, ce qui disposera les items flex en rangée dans le mode d'écriture que vous utilisez — en français les items sont donc alignés horizontalement quand nous créons un conteneur flex. Nous pouvons changer la direction de l'axe principal avec flex-direction: column
et les items s'aligneront sur une colonne, ce qui signifie qu'ils seront disposés selon la direction block pour ce mode d'écriture.
C'est parce qu'il est possibe de changer la direction de l'axe que la question la plus importante à se poser en Flexbox est "quel axe est mon axe principal?". Une fois que vous le savez, l'alignement (sur votre axe principal) s'effectue via justify-content
. Peu importe que votre axe principal soit une rangée ou une colonne. Vous contrôlez l'espace entre les items flex avec justify-content
.
Sur l'axe perpendiculaire, vous pouvez utiliser align-items
qui alignera les items à l'intérieur du conteneur flex ou de la ligne flex si votre conteneur flex a plusieurs lignes. Si vous avez un conteneur flex comportant plusieurs lignes utilisant flex-wrap: wrap
et qu'il y a de l'espace libre dans ce conteneur, vous pouvez utiliser align-content
pour répartir l'espace sur l'axe perpendiculaire.
L'exemple suivant montre un conteneur flex affiché comme rangée puis comme colonne :
Quand justify-content ou align-content ne marchent pas
Les propriétés justify-content
et align-content
de Grid et Flexbox servent à distribuer l'espace libre. Il convient donc de vérifier que vous avez bien de l'espace disponible.
Voici un exemple flex. J'ai réglé la direction de l'axe principal flex-direction: row
et j'ai trois items. Ils n'occupent pas tout l'espace dans le conteneur, j'ai encore de la place sur l'axe principal, la valeur initiale de justify-content
est flex-start
, par conséquent mes items s'alignent tous à partir du point de départ et il me reste de l'espace disponible à la fin. Sur cette vue, l'espace est mis en valeur par l'Inspecteur de Firefox.
Si je change la valeur de flex-direction
pour space-between
, l'espace disponible est maintenant réparti entre les items :
Si j'ajoute maintenant du contenu supplémentaire à mes items, de façon à ce qu'ils deviennent plus longs et et que je n'aie plus d'espace disponible, alors justify-content
ne fait plus rien. Tout simplement parce qu'il n'y a plus d'espace à répartir.
On me pose souvent la question de savoir pourquoi justify-content
ne fonctionne pas lorsque flex-direction
a pour valeur column
. Eh bien c'est généralement parce qu'il n'y a pas d'espace à répartir. Si vous reprenez l'exemple qui précède, et que vous le transformez en flex-direction: column
, les items s'afficheront en colonne mais il n'y aura pas d'espace disponible en-dessous des items comme c'est le cas avec flex-direction: row
. Pourquoi ? Parce que quand vous créez un conteneur flex avec display: flex
, vous avez un conteneur flex de niveau bloc. Il prendra tout l'espace possible dans la direction inline. En CSS, les objets ne s'étirent pas dans la direction bloc, donc pas d'espace supplémentaire disponible.
Ajoutez une hauteur à votre conteneur et — s'il y a plus d'espace que nécessaire pour afficher les items — vous aurez de l'espace disponible et justify-content
fonctionnera sur votre colonne.
Pourquoi n'y a-t-il pas de justify-self dans Flexbox ?
Grid Layout implémente toutes les propriétés de boîtes pour chacun des axes parce que nous avons toujours affaire à deux axes dans Grid. Nous créons des pistes (qui peuvent laisser de l'espace supplémentaire dans le conteneur grid, pour chacune des directions) et donc nous pouvons répartir cet espace avec align-content
ou justify-content
. Nous avons également les zones de grille (grid-areas) et il arrive que l'élément n'occupe pas tout l'espace de cette zone, nous pouvons alors utiliser align-self
ou justify-self
pour déplacer le contenu dans la zone (ou bien align-items
, justify-items
pour changer l'alignement de tous les items).
Contrairement à Grid, Flexbox n'a pas de pistes. Sur l'axe principal, tout ce que nous pouvons faire c'est répartir l'espace entre les items. Pas de piste, pas de zone non plus pour répartir les items.C'est pourquoi il n'y a pas de propriété justify-self
sur l'axe principal dans Flexbox.
Parfois cependant, vous voudrez avoir la possibilité d'aligner un item ou une partie d'un groupe d'items d'une autre façon. Un pattern assez courant serait une barre de navigation éclatée, avec un item séparé du reste du groupe. Dans ce type de situation, la spécification conseille l'utilisation de marges automatiques.
Une marge auto
prendra tout l'espace dans la direction où elle est appliquée, ce qui explique qu'on puisse centrer un bloc (par exemple notre page principale) avec des marges gauche et droite auto. Lorsqu'on a margin auto des deux côtés, chacune des marges essaie de prendre tout l'espace et repousse le bloc vers le centre. Pour notre rangée d'items flex, nous pouvons ajouter margin-left: auto
à l'item que nous voulons séparer, et tant qu'il reste de l'espace disponible dans le conteneur flex, nous avons une séparation. Et dès qu'il n'y a plus d'espace supplémentaire disponible, les items reprennent leur comportement habituel d'items flex.
Flexbox et les micro-composants
Un point qu'on néglige souvent c'est l'utilité de Flexbox pour résoudre de micro-tâches de mise en page, là où parfois on penserait que vertical-align
est la solution. J'utilise souvent Flexbox pour obtenir de beaux alignements de petits motifs, par exemple aligner une icône sur un texte, aligner deux textes de fontes différentes sur leur ligne de base, ou aligner correctement des champs de formulaires avec les boutons. Si vous vous débattez avec vertical-align
, essayez Flexbox. Et n'oubliez pas que vous pouvez créer un conteneur flex inline si vous voulez avec display: inline-flex
.
Rien n'interdit d'utiliser Flexbox ou même Grid pour de petites tâches de mise en page.Ils ne sont aucunement réservés aux grands layouts. Faites des essais avec ce qui est disponible et voyez ce qui vous convient le mieux.
On se demande souvent ce qui est la bonne ou la mauvaise manière de faire quelque chose. En réalité, il n'y a souvent pas ne bon ou de mauvais. Une petite différence dans votre pattern aura pour conséquence que Flexbox est la solution la plus appropriée, là où sinon vous utiliseriez plutôt vertical-align
.
En résumé
Pour récapituler, voici un résumé rapide des bases de l'alignement. Si vous gardez ces quelques règles en mémoire, vous devriez pouvoir aligner à peu près tout.
- Alignement de texte ou d'élément inline ➜
text-align
,vertical-align
etline-height
. - Item à aligner au centre d'une page ou d'un conteneur ➜ faites du conteneur un conteneur flex et utilisez
align-items: center
etjustify-content: center
. - Pour les mises en page Grid, les propriétés commençant par
align-
fonctionnent dans la direction bloc. Celles qui commencent parjustify-
fonctionnent dans la direction inline. - Pour les mises en page Flex, les propriétés commençant par
align-
fonctionnent sur l'axe perpendiculaire. Celles qui commencent parjustify-
fonctionnent sur l'axe principal. - Les propriétés
justify-content
etalign-content
répartissent l'espace supplémentaire. Si vous n'avez pas d'espace supplémentaire disponibledans votre conteneur flex ou grid, ces propriétés ne feront rien. - Si vous pensez avoir besoin de
justify-self
dans Flexbox, peut-être une marge auto vous donnera-t-elle la solution. - Vous pouvez utiliser Grid et Flexbox et les propriétés d'alignement pour de micro tâches aussi bien que pour vos composants essentiels. Expérimentez !
Pour plus d'information sur les alignements, consultez ces ressources :