La Cascade

Un peu de tout sur CSS, HTML, SVG et JS,traduit du web anglophone
Rechercher

Alignement en CSS, un guide complet

par Rachel Andrew, 18 mai 2019, css, flexbox, cssgrid, article original paru le 28 mars 2019 dans Smashing Magazine

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").

voir vertical-align de rachelandrew dans 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.

voir vertical-align de rachelandrew dans CodePen

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 :

  1. On a de l'espace libre dans notre container flex ou dans notre grille (une fois les éléments ou les pistes affichées).
  2. 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.

voir le justify-content and align-content de rachelandrew dans CodePen

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.

voir Block axis alignment de rachelandrew dans CodePen

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.

voir Inline axis alignment de rachelandrew dans CodePen

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.

voir justify-content in flexbox de rachelandrew dans CodePen

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 :

voir Cross axis alignment flexbox de rachelandrew dans CodePen

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.

les items s'alignent tous à partir du point de départ et il reste de l'espace disponible à la fin

Si je change la valeur de flex-direction pour space-between, l'espace disponible est maintenant réparti entre les items :

les items s'alignent régulièrement à partir du point de départ, l'espace disponible est réparti entre les items, et il ne reste pas d'espace disponible à la fin

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.

les items sont répartis sur tout l'espace et il n'y a pas d'espace entre eux

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.

chaque item s'étend sur tout l'espace horizontal, et ils sont superposés, sans espace entre eux, dans la direction verticale

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.

comme précédemment, mais le conteneur étant plus haut, il y a maintenant de l'espace entre les items, dans la direction verticale

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.

voir auto margins de rachelandrew dans CodePen

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.

voir inline-flex de rachelandrew dans CodePen

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.

  1. Alignement de texte ou d'élément inline   ➜   text-align, vertical-align et line-height.
  2. Item à aligner au centre d'une page ou d'un conteneur   ➜   faites du conteneur un conteneur flex et utilisez align-items: center et justify-content: center.
  3. Pour les mises en page Grid, les propriétés commençant par align- fonctionnent dans la direction bloc. Celles qui commencent par justify- fonctionnent dans la direction inline.
  4. Pour les mises en page Flex, les propriétés commençant par align- fonctionnent sur l'axe perpendiculaire. Celles qui commencent par justify- fonctionnent sur l'axe principal.
  5. Les propriétés justify-content et align-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.
  6. Si vous pensez avoir besoin de justify-self dans Flexbox, peut-être une marge auto vous donnera-t-elle la solution.
  7. 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 :

Autres ressources externes

Articles de Rachel Andrew traduits dans La Cascade

Voir la page de Rachel Andrew et la liste de ses articles dans La Cascade.
Article original paru le 28 mars 2019 dans Smashing Magazine
Traduit avec l'aimable autorisation de Smashing Magazine et de Rachel Andrew.
Copyright Smashing Magazine © 2019