web-dev-qa-db-fra.com

Comment le flex-wrap fonctionne-t-il avec align-self, align-items et align-content?

align-self

Dans le code suivant, align-self marche avec flex-wrap: nowrap.

enter image description here

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Mais lorsque le conteneur est basculé sur flex-wrap: wrap, le align-self _ propriété échoue.

enter image description here

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

align-items

De même, pourquoi align-items travailler ici (wrap désactivé):

enter image description here

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

... mais pas ici (habillage activé):

enter image description here

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

align-content

Avec flex-wrap: nowrap, le align-content propriété ne centre pas verticalement les éléments flex ici:

enter image description here

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: center;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Mais étrangement, si le bouclage est activé et que align-content est omis, le conteneur crée de grands écarts entre les lignes:

enter image description here

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Et align-self fonctionne à nouveau.

enter image description here

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

flex-item:nth-child(even) {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Comment fonctionne flex-wrap travailler avec align-self, align-items et align-content?

54
Michael_B

Réponse courte

Bien que la propriété flex-wrap Semble assez basique - elle contrôle si les éléments flexibles peuvent être renvoyée à la ligne - elle a en fait un impact étendu sur l'ensemble de la mise en page flexbox.

La propriété flex-wrap Détermine le type de conteneur flex que vous utiliserez.

  • flex-wrap: nowrap Crée un conteneur flex sur une seule ligne
  • flex-wrap: wrap Et wrap-reverse Créent un conteneur multi-lignes flex

Les propriétés align-items Et align-self Fonctionnent dans les conteneurs à une ou plusieurs lignes. Cependant, ils ne peuvent avoir d'effet que s'il existe un espace libre dans l'axe transversal de la ligne de flexion.

La propriété align-content Ne fonctionne que dans des conteneurs multilignes. Il est ignoré dans les conteneurs à une seule ligne.


Explication

Le spécification flexbox fournit quatre propriétés de mot clé pour aligner les éléments flex:

  • align-items
  • align-self
  • align-content
  • justify-content

Pour comprendre les fonctions de ces propriétés, il est important d’abord de comprendre la structure d’un conteneur Flex.


Partie 1: Comprendre l'axe principal et l'axe transversal d'un conteneur Flex

Les axes X et Y

Un conteneur flexible fonctionne dans deux directions: axe x (horizontal) et axe y (vertical).

x-axis and the y-axis

Source: Wikipedia

Les éléments enfants d'un conteneur Flex, appelés "éléments Flex", peuvent être alignés dans les deux sens.

C'est l'alignement de flex à son niveau le plus fondamental.

Les axes principal et transversal

En superposition des axes x et y, les axes main et croix sont superposés.

Par défaut, l'axe principal est horizontal (axe des x) et l'axe transversal est vertical (axe des y). C'est le réglage initial, tel que défini par le spécification flexbox .

flex main axis and cross axis

Source: W3C

Cependant, contrairement aux axes x et y, qui sont fixes, les axes principal et transversal peuvent changer de direction.

La propriété flex-direction

Dans l'image ci-dessus, l'axe principal est horizontal et l'axe transversal est vertical. Comme mentionné précédemment, il s'agit d'un paramètre initial d'un conteneur flexible.

Cependant, ces directions peuvent être facilement commutées avec la propriété flex-direction. Cette propriété contrôle la direction de l'axe principal; il détermine si les éléments flexibles sont alignés verticalement ou horizontalement.

D'après les spécifications:

5.1. Sens du flux: la propriété flex-direction

La propriété flex-direction Spécifie comment les éléments flex sont placés dans le conteneur flex, en définissant la direction de l’axe principal du conteneur flex. Cela détermine la direction dans laquelle les éléments flexibles sont disposés.

Il existe quatre valeurs pour la propriété flex-direction:

/* main axis is horizontal, cross axis is vertical */
flex-direction: row; /* default */
flex-direction: row-reverse;

/* main axis is vertical, cross axis is horizontal */    
flex-direction: column;
flex-direction: column-reverse;

L'axe transversal est toujours perpendiculaire à l'axe principal.


Partie 2: Lignes flexibles

Dans le conteneur, les éléments flexibles existent dans une ligne, appelée "ligne flex".

Une ligne de flexion est une ligne ou une colonne, selon flex-direction.

Un conteneur peut avoir une ou plusieurs lignes, en fonction de flex-wrap.

Conteneur Flex monoligne

flex-wrap: nowrap Établit un conteneur flex sur une seule ligne, dans lequel les éléments flex sont forcés de rester sur une seule ligne (même s'ils débordent du conteneur).

a single-line flex container (one column)

L'image ci-dessus a une ligne de flex.

flex-container {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap; /* <-- allows single-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  width: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Conteneur multi-lignes Flex

flex-wrap: wrap Ou wrap-reverse Établit un conteneur flex multiligne, dans lequel les éléments flex peuvent créer de nouvelles lignes.

multi-line flex container (3 columns)

L'image ci-dessus a trois lignes de flex.

flex-container {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap; /* <-- allows multi-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  width: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

multi-line flex container (3 rows)

L'image ci-dessus a trois lignes de flex.

flex-container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap; /* <-- allows multi-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Partie 3: Propriétés d'alignement des mots clés

Les propriétés sont attribuées aux axes principal et transversal (et non les axes X et Y)

Alors que la propriété flex-direction Contrôle l'orientation des éléments flexibles, quatre propriétés contrôlent l'alignement et le positionnement. Ceux-ci sont:

  • align-items
  • align-self
  • align-content
  • justify-content

Chacune de ces propriétés est affectée en permanence à un axe.

La propriété justify-content Ne fonctionne que sur l'axe principal.

Les trois propriétés align-* Ne fonctionnent que sur l'axe transversal.

C'est une erreur courante de supposer que ces propriétés sont fixées aux axes x et y. Par exemple, justify-content Est toujours horizontal et align-items Est toujours vertical.

Cependant, lorsque flex-direction Est commuté sur column, l'axe principal devient l'axe des y et justify-content Fonctionne verticalement.

L'objectif de ce post est l'alignement transversal. Pour une explication de l'alignement sur l'axe principal et de la propriété justify-content, Voir ce post:

Définitions

La spécification flexbox) fournit trois propriétés de mot clé pour l'alignement transversal:

  • align-items
  • align-self
  • align-content

align-items/align-self

La propriété align-items Aligne les éléments flexibles le long de l'axe transversal de la ligne flex. Cela s'applique aux conteneurs flexibles.

La propriété align-self Est utilisée pour remplacer align-items Sur des éléments flexibles individuels. Cela s'applique aux articles flexibles.

Voici la définition de la spécification:

8.3. Alignement transversal: les propriétés align-items Et align-self

Les éléments flexibles peuvent être alignés dans l'axe transversal de la ligne actuelle du conteneur flex, comme dans justify-content Mais dans la direction perpendiculaire. align-items Définit l’alignement par défaut de tous les éléments du conteneur flex. align-self Permet de remplacer cet alignement par défaut pour des éléments flexibles individuels.

Il y a six valeurs possibles pour align-items/align-self:

  • flex-start
  • flex-end
  • center
  • baseline
  • stretch
  • auto (align-self uniquement)

(Pour une description de chaque valeur, cliquez sur l'en-tête de définition de spécification ci-dessus.)

La valeur initiale de align-items Est stretch, ce qui signifie que les éléments flexibles étendront toute la longueur disponible de l'axe transversal du conteneur.

La valeur initiale de align-self Est auto, ce qui signifie qu'elle hérite de la valeur de align-items.

Vous trouverez ci-dessous une illustration de l’effet de chaque valeur dans un conteneur dans le sens des lignes.

align-items align-self values

source: W3C

align-content

Cette propriété est légèrement plus complexe que align-items Et align-self.

Voici la définition de la spécification:

8.4. Lignes d'emballage flexibles: la propriété align-content

La propriété align-content Aligne les lignes d’un conteneur Flex dans le conteneur Flex lorsque l’axe transversal contient davantage d’espace, comme le fait justify-content Pour aligner des éléments individuels dans l’axe principal. Notez que cette propriété n'a aucun effet sur un conteneur flex sur une seule ligne.

Contrairement à align-items Et à align-self, Qui déplacent les éléments flexibles dans leur ligne, align-content Déplace les lignes flexibles dans le conteneur .

Il y a les six valeurs possibles pour align-content:

  • flex-start
  • flex-end
  • center
  • space-between
  • space-around
  • stretch

(Pour une description de chaque valeur, cliquez sur l'en-tête de définition de spécification ci-dessus.)

Vous trouverez ci-dessous une illustration de l’effet de chaque valeur dans un conteneur dans le sens des lignes.

enter image description here

source: W3C

Pourquoi align-content Ne fonctionne-t-il que dans des conteneurs flex multilignes?

Dans un conteneur Flex à une seule ligne, la taille transversale de la ligne est égale à la taille transversale du conteneur. Cela signifie qu'il n'y a pas d'espace libre entre la ligne et le conteneur. En conséquence, align-content Ne peut avoir aucun effet.

Voici le section pertinente de la spécification :

Seuls les conteneurs Flex multilignes ont toujours un espace libre dans l'axe transversal pour l'alignement des lignes, car dans un conteneur Flex à une ligne, la ligne unique s'étire automatiquement pour remplir l'espace.


Partie 4: Exemples expliqués

enter image description here

Dans l'exemple n ° 1, align-self Fonctionne avec flex-wrap: nowrap Car les éléments flexibles existent dans un conteneur à une seule ligne. Par conséquent, il existe une ligne de flexion qui correspond à la hauteur du conteneur.

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

Dans l'exemple n ° 2, align-self Échoue car il existe dans un conteneur multiligne (flex-wrap: wrap) etalign-content Est défini sur flex-start. Cela signifie que les lignes de flexion sont serrées au début de l'axe transversal, ne laissant aucun espace libre pour que align-self Fonctionne.

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

L'explication de l'exemple n ° 3 est la même que celle de l'exemple n ° 1.

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

L'explication de l'exemple n ° 4 est la même que celle de l'exemple n ° 2.

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

L'exemple n ° 5 est un conteneur d'une seule ligne. En tant que tel, la taille transversale de la ligne de flexion est égale à la taille transversale du conteneur, ne laissant aucun espace supplémentaire entre les deux. Par conséquent, align-content, Qui aligne les lignes de flexion lorsqu'il y a un espace supplémentaire dans l'axe transversal, n'a aucun effet.

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: center;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

Le réglage initial pour align-content Est stretch. Cela signifie que si aucune autre valeur n'est spécifiée, le conteneur répartira l'espace disponible de manière uniforme entre les lignes flexibles. (Un effet similaire est créé sur l'axe principal lorsque tous les éléments flexibles obtiennent flex: 1.)

Cette répartition de l'espace entre les lignes peut provoquer de grands écarts entre les lignes/colonnes. Moins de lignes entraînent des écarts plus importants. Plus le nombre de lignes est réduit, plus chaque espace occupe une petite partie de l'espace.

Pour résoudre ce problème, passez de align-content: stretch À align-content: flex-start. Ceci regroupe les lignes (voir exemples 2 et 4 ci-dessus). Bien sûr, cela élimine également tout espace libre dans la ligne et align-items Et align-self Ne peuvent plus fonctionner.

Voici un article connexe: Supprimez l'espace (les espaces) entre plusieurs lignes d'éléments flexibles lorsqu'ils se terminent

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

Comme expliqué dans les exemples précédents, avec align-content: stretch, Il peut y avoir un espace supplémentaire dans les lignes de flexion, ce qui permet à align-items Et align-self De fonctionner. Toute autre valeur pour align-content Encapsulerait les lignes, en éliminant l'espace supplémentaire et en rendant align-items Et align-self Inutiles.

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

flex-item:nth-child(even) {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>
96
Michael_B

Tout d'abord, align-content est inutile s'il n'y a pas de wrap:

doc w3c

La propriété align-content aligne les lignes d’un conteneur Flex dans le conteneur Flex lorsque l’axe transversal contient un espace supplémentaire, ce qui est similaire à la façon dont justification-contenu aligne les éléments individuels dans l’axe principal. Notez que cette propriété n'a aucun effet sur un conteneur flex sur une seule ligne.

De plus, dans votre deuxième cas, align-self n'échoue pas. C'est inutile car les lignes intérieures ont été emballées. Créons un espace pour que le style puisse fonctionner:

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}
flex-item:nth-child(5) {
  height: 90px;  /* added */
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

De même, dans votre 4ème exemple, le style fonctionne, si vous définissez les conditions dans lesquelles il peut être vu.

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:nth-child(2),flex-item:nth-child(5) {
  height: 90px;  /* added */
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Enfin, lorsque vous commentez le contenu d'alignement, il retourne à stretch, c'est pourquoi les lignes augmentent la taille pour remplir le conteneur.

stretch Les lignes s'étirent pour occuper l'espace restant. Si l'espace libre restant est négatif, cette valeur est identique à flex-start. Sinon, l'espace libre est divisé de manière égale entre toutes les lignes, ce qui augmente la taille des croix.

4
vals