CSS Flexbox et l'alignement, guide complet
Dans cet article, nous examinons les propriétés d'alignement de Flexbox tout en découvrant quelques règles de base qui nous aideront à nous rappeler comment elles fonctionnent sur les axes principal et transversal
Dans le premier article de cette série, j'ai expliqué ce qui se passait lorsqu'on déclare display: flex
sur un élément. Ici, nous allons examiner les propriétés d'alignement et la façon dont elles fonctionnent dans Flexbox. Si align
et justify
vous ont donné des migraines par le passé, j'espère que cet article rendra les choses plus claires !
Une histoire de l'alignement Flexbox
Depuis le début de CSS Layout, l'alignement correct des éléments sur les deux axes a toujours semblé le problème le plus ardu en matière de conception de sites Web. La capacité d'aligner correctement des éléments et des groupes d'éléments a donc été, pour beaucoup d'entre nous, l'apport le plus excitant de Flexbox. L'alignement est devenu aussi simple que deux lignes de CSS :
Les propriétés d'alignement que vous considérez peut-être comme des propriétés Flexbox sont maintenant entièrement définies dans la spécification d'alignement de boîte (Box Alignment). Cette spécification détaille le fonctionnement de l'alignement dans les divers contextes de layout. Cela signifie que nous pouvons utiliser les mêmes propriétés d'alignement dans CSS Grid que celles utilisées dans Flexbox – et à l'avenir dans d'autres contextes de layout. Par conséquent, toute nouvelle capacité d'alignement pour Flexbox sera décrite en détail dans la spécification Box Alignment et non dans un futur niveau de Flexbox.
Les Propriétés
Beaucoup de gens me disent qu’ils ont du mal à se rappeler s’ils doivent utiliser des propriétés qui commencent par align-
ou celles qui commencent par justify-
dans Flexbox. Ce qu'il faut retenir :
justify-
effectue l'alignement de l'axe principal. Alignement dans la même direction que votreflex-direction
align-
effectue un alignement transversal. Alignement dans la direction perpendiculaire à votreflex-direction
.
Il est vraiment utile ici de penser en termes d’axe principal et d’axe transversal plutôt que d’horizontale et de verticale.
Alignement sur l'axe principal avec justify-content
Commençons par l'alignement de l'axe principal. Sur cet axe, nous alignons à l'aide de la propriété justify-content
. Cette propriété considère l'ensemble de nos éléments flexibles comme un groupe et contrôle la répartition de l'espace entre les éléments.
La valeur initiale de justify-content
est flex-start
. C’est pourquoi, lorsque vous déclarez display: flex
, tous les items flexibles sont alignés à partir du début de la ligne flex. Si vous avez une flex-direction
de row
et que vous parlez une langue écrite de gauche à droite comme l'anglais, les éléments commenceront à gauche.
Remarquez que la propriété justify-content
ne peut faire quelque chose que s'il y a un espace disponible à distribuer. Par conséquent, si vos items flexibles occupent toute la place sur l'axe principal, l'utilisation de justify-content
ne changera rien.
Si nous donnons à justify-content
la valeur flex-end
, alors tous les items sont déplacés vers la fin de la ligne. L'espace disponible, s'il y en a, est maintenant placé en début de ligne.
Nous pouvons faire d'autres choses avec cet espace. Nous pourrions souhaiter qu’il soit distribué entre nos items flexibles, en utilisant justify-content: space-between
. Dans ce cas, le premier et le dernier élément seront alignés avec les extrémités du conteneur et tout l’espace sera partagé de manière égale entre les éléments.
Nous pouvons demander que l’espace soit réparti autour de nos éléments flexibles, en utilisant justify-content: space-around
. Dans ce cas, l'espace disponible est partagé et placé de chaque côté de l'élément.
Une valeur plus récente de justify-content
peut être trouvée dans la spécification Box Alignment. Elle n'apparaît pas dans la spécification Flexbox. Cette valeur est space-evenly
. Dans ce cas, les éléments seront répartis de manière uniforme dans le conteneur et l'espace supplémentaire sera partagé entre les éléments et de chaque côté.
Vous pouvez jouer avec toutes ces valeurs dans la démo :
Ces valeurs fonctionnent de la même manière si votre flex-direction
est column
. Il est possible toutefois que la colonne n'offre pas autant d'espace disponible, à moins d'ajouter une hauteur ou une dimension de bloc au conteneur flex comme dans la démo suivante :
Alignement sur l'axe transversal avec align-content
Si vous avez ajouté flex-wrap: wrap
à votre conteneur flex et que vous avez plusieurs lignes flex, vous pouvez utiliser align-content
pour aligner vos lignes flex sur l'axe transversal. Toutefois, il vous faudra disposer d'un espace supplémentaire sur l'axe transversal. Dans la démonstration ci-dessous, mon axe transversal fonctionne dans la direction bloc comme une colonne et j'ai défini la hauteur du conteneur flex à 60vh. C'est plus que l'espace nécessaire pour afficher mes items flex, j'ai donc de la place verticalement dans le conteneur.
Je peux ensuite utiliser align-content
avec les valeurs ci-dessous :
Si ma flex-direction
était column
alors align-content
fonctionnerait comme dans l'exemple suivant :
Tout comme précédemment avec justify-content
, nous traitons les lignes comme un groupe et nous distribuons l'espace disponible.
Le raccourci place-content
Dans la spécification Box Alignment, on trouve le raccourci place-content
. Avec cette propriété, vous pouvez définir en même temps justify-content
et align-content
. La première valeur est pour align-content
, la seconde pour justify-content
:
.container {
place-content: space-between stretch;
}
équivaut à :
.container {
align-content: space-between;
justify-content: stretch;
}
Si par contre vous ne définissez qu'une seule valeur, align-content
et justify-content
prennent cette valeur :
.container {
place-content: space-between;
}
équivaut à :
.container {
align-content: space-between;
justify-content: space-between;
}
Alignement sur l'axe transversal avec align-items
Nous savons maintenant que nous pouvons aligner notre ensemble d'items flex ou nos lignes flex comme un groupe. Cependant, nous pourrions souhaiter aligner nos éléments d’une autre manière : aligner les éléments les uns par rapport aux autres sur l’axe transversal. Votre conteneur flex a une hauteur. Cette hauteur peut être définie par la hauteur de l'élément le plus grand, comme dans cette image.
Mais on pourrait aussi la définir en ajoutant une hauteur au conteneur flex :
La raison pour laquelle les éléments flexibles semblent s’étirer jusqu’à atteindre la taille de l’élément le plus grand est que la valeur initiale d’align-items
est stretch
. Les items s'étirent sur l'axe transversal pour prendre la taille du conteneur flexible dans cette direction.
Notez qu'en ce qui concerne align-items
, si vous avez un conteneur flex multi-lignes, chaque ligne se comporte comme un nouveau conteneur Flex. L'item le plus grand de cette ligne définirait la taille de tous les items de cette ligne.
En plus de la valeur initiale de stretch, vous pouvez attribuer à align-items
la valeur de flex-start
. Dans ce cas, les items s'alignent au début du conteneur et ne s'étirent plus en hauteur.
La valeur flex-end
les déplace à la fin de l'axe transversal :
Si vous utilisez la valeur center
, les items sont centrés les uns par rapport aux autres :
Enfin, nous pouvons aligner les items sur la ligne de base, permettant ainsi de s'assurer que le texte est aligné, ce qui ne serait pas nécessairement le cas si l'alignement se faisait sur le contenu.
Vous pouvez jouer avec toutes ces valeurs dans la démo :
Alignement individuel avec align-self
La propriété align-items
vous permet de définir l'alignement de tous les éléments en même temps. En réalité, cela permet de définir toutes les valeurs align-self
sur les éléments flex individuels de manière groupée. Vous pouvez également utiliser la propriété align-self
sur tout élément flex individuel pour l'aligner à l'intérieur de la ligne flex et par rapport aux autres éléments flex.
Dans l'exemple suivant, j'ai utilisé align-items
sur le conteneur pour définir l'alignement du groupe sur center
, mais j'ai également utilisé align-self
sur le premier et le dernier éléments pour modifier leur valeur d'alignement (vérifiez en cliquant sur CSS).
Pourquoi n'y a-t-il pas de justify-self ?
Une question souvent posée est de savoir pourquoi il n'est pas possible d'aligner un élément ou un groupe d'éléments sur l'axe principal. Pourquoi n'y a-t-il pas de propriété -self
pour l'alignement sur l'axe principal dans Flexbox ? Si vous considérez justify-content
et align-content
comme étant une façon de distribuer l'espace, la raison pour laquelle ils ne sont pas auto-alignés devient plus évidente. Nous traitons les éléments flexibles en tant que groupe et distribuons l'espace disponible d'une manière ou d'une autre - au début ou à la fin du groupe, ou entre les éléments.
Il pourrait également être utile de réfléchir à la manière dont justify-content
et align-content
fonctionnent dans CSS Grid Layout. Dans Grid, ces propriétés sont utilisées pour répartir l'espace disponible dans le conteneur de grille entre les pistes (tracks) de la grille. Une fois encore, nous prenons les pistes en tant que groupe et ces propriétés nous permettent de répartir l'éventuel espace supplémentaire entre elles. Comme nous agissons sur un groupe, à la fois dans Grid et dans Flexbox, nous ne pouvons pas cibler un élément seul et faire quelque chose de différent avec celui-ci. Cependant, il existe un moyen de réaliser le type de présentation auquel vous pensez lorsque vous souhaitez une propriété -self
sur l'axe principal, et ce moyen c'est l'utilisation de marges automatiques.
Utiliser les marges automatiques sur l'axe principal
Si vous avez déjà centré un bloc dans CSS (par exemple le wrapper du contenu de votre page principale, en définissant une marge auto
à gauche et à droite), vous avez déjà une expérience du comportement des marges automatiques. Une marge réglée sur auto
essayera de devenir aussi grande que possible dans la direction dans laquelle elle a été définie. Lorsque les marges sont utilisées pour centrer un bloc, nous définissons les positions gauche et droite sur auto
, chacune essaye de prendre le plus de place possible et pousse notre bloc au centre.
Les marges automatiques fonctionnent très bien dans Flexbox pour aligner des éléments uniques ou des groupes d’éléments sur l’axe principal. Dans l'exemple qui suit, je réalise un design pattern très courant. J'ai une barre de navigation utilisant Flexbox, les éléments sont affichés sur une ligne et utilisent la valeur initiale de justify-content: start
. J'aimerais que le dernier élément soit affiché séparément des autres, à la fin de la ligne flex – en supposant qu'il y ait suffisamment d'espace sur la ligne pour le faire.
Je cible cet item et je lui donne une marge gauche auto
. Cela a pour effet que la marge essaie d'obtenir le plus d'espace possible à gauche de l'élément, ce qui entraîne le déplacement de l'élément complètement à droite.
Si vous utilisez les marges automatiques sur l'axe principal, justify-content
n'aura plus d'effet puisque les marges automatiques auront pris tout l'espace qui aurait pu être utilisé par justify-content
.
Alignement de repli
Chaque méthode d’alignement détaille un alignement de repli (fallback), c’est à dire ce qui se produira si l’alignement que vous avez demandé ne peut pas être réalisé. Par exemple, si vous n'avez qu'un seul élément dans un conteneur flexible et demandez justify-content: space-between
, que devrait-il se passer ? La réponse est que l'alignement de repli flex-start
est utilisé et que votre item individuel s'alignera au début du conteneur flex. Dans le cas de justify-content: space-around
, un alignement de repli center
est utilisé.
Dans la spécification actuelle, vous ne pouvez pas modifier l'alignement de repli. Si vous préférez que le repli de space-between
soit center
plutôt que flex-start
, il n'y a pas moyen de le faire. Cependant, une note dans la spécification indique que les niveaux futurs devraient le permettre.
Alignement safe et unsafe
Un ajout plus récent à la spécification Box Alignment est le concept d'alignement sécurisé / non sécurisé à l'aide des mots clés safe
et unsafe
.
Dans le code suivant, le dernier élément est trop large pour le conteneur et, avec un alignement non sécurisé et le conteneur flexible sur le côté gauche de la page, l'élément est coupé : le débordement se situe en dehors des limites de la page.
.container {
display: flex;
flex-direction: column;
width: 100px;
align-items: unsafe center;
}
.item:last-child {
width: 200px;
}
Un alignement sécurisé évite la perte de données, en déplaçant le débordement vers l'autre côté.
.container {
display: flex;
flex-direction: column;
width: 100px;
align-items: safe center;
}
.item:last-child {
width: 200px;
}
Ces mots-clés ont un support navigateur encore limité mais ils sont une bonne illustration du contrôle supplémentaire apporté à Flexbox via la spécification Box Alignment.
Récapitulation
Les propriétés d'alignement ont commencé sous forme de liste dans Flexbox, mais elles ont maintenant leur propre spécification et s'appliquent à d'autres contextes de layout. Quelques points-clés vous aideront à vous rappeler comment les utiliser dans Flexbox:
justify-
l'axe principal etalign-
l'axe transversal;- Pour utiliser
align-content
etjustify-content
, vous avez besoin d'espace disponible. - Les propriétés
align-content
etjustify-content
traitent les éléments en tant que groupe, en partageant de l'espace. Par conséquent, vous ne pouvez pas cibler un élément individuel et il n’existe donc pas d’alignement de type-self
pour ces propriétés; - Si vous souhaitez aligner un élément ou diviser un groupe sur l'axe principal, utilisez les marges automatiques pour le faire.
- La propriété
align-items
définit toutes les valeursalign-self
en tant que groupe. Utilisezalign-self
sur le flex enfant pour définir la valeur d'un élément individuel.