web-dev-qa-db-fra.com

Dans CSS Flexbox, pourquoi n'y a-t-il pas de propriétés "justifier-éléments" et "justifier-soi"?

Considérez l’axe principal et l’axe transversal d’un conteneur flexible:

enter image description hereSource: W3C

Pour aligner les éléments flexibles le long de l’axe principal, il existe une propriété:

Pour aligner les éléments flexibles le long de l’axe transversal, il existe trois propriétés:

Dans l'image ci-dessus, l'axe principal est horizontal et l'axe transversal est vertical. Ce sont les directions par défaut d'un conteneur Flex.

Cependant, ces directions peuvent être facilement échangées avec la propriété flex-direction .

_/* main axis is horizontal, cross axis is vertical */
flex-direction: row;
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.)

Mon propos en décrivant le fonctionnement des axes est qu’il ne semble y avoir de particularité dans aucune des directions. Axe principal, axe transversal, ils sont égaux en importance et _flex-direction_ facilite les échanges.

Alors pourquoi l'axe transversal obtient-il deux propriétés d'alignement supplémentaires?

Pourquoi _align-content_ et _align-items_ sont-ils consolidés dans une propriété unique pour l'axe principal?

Pourquoi l'axe principal n'a-t-il pas une propriété _justify-self_?


Scénarios où ces propriétés seraient utiles:

  • placer un article flexible dans le coin du conteneur flexible
    _#box3 { align-self: flex-end; justify-self: flex-end; }_

  • aligner un groupe d'éléments flexibles à droite (_justify-content: flex-end_) mais faire en sorte que le premier élément s'aligne à gauche (_justify-self: flex-start_)

    Considérons une section d'en-tête avec un groupe d'éléments de navigation et un logo. Avec _justify-self_, le logo peut être aligné à gauche, tandis que les éléments de navigation restent tout à fait à droite, et le tout s’ajuste sans à-coups ("fléchit") à différentes tailles d’écran.

  • dans une rangée de trois éléments flexibles, fixez l'élément central au centre du conteneur (_justify-content: center_) et alignez les éléments adjacents sur les bords du conteneur (_justify-self: flex-start_ et _justify-self: flex-end_).

    Notez que les valeurs _space-around_ et _space-between_ sur _justify-content_ ne garderont pas l'élément du milieu centré par rapport au conteneur si les éléments adjacents ont des largeurs différentes.

_#container {
  display: flex;
  justify-content: space-between;
  background-color: lightyellow;
}
.box {
  height: 50px;
  width: 75px;
  background-color: springgreen;
}
.box1 {
  width: 100px;
}
.box3 {
  width: 200px;
}
#center {
  text-align: center;
  margin-bottom: 5px;
}
#center > span {
  background-color: aqua;
  padding: 2px;
}_
_<div id="center">
  <span>TRUE CENTER</span>
</div>

<div id="container">
  <div class="box box1"></div>
  <div class="box box2"></div>
  <div class="box box3"></div>
</div>

<p>note that the middle box will only be truly centered if adjacent boxes are equal width</p>_

version jsFiddle


Au moment de la rédaction de ce document, il n’est fait aucune mention de _justify-self_ ou _justify-items_ dans le flexbox spec .

Cependant, dans le CSS Box Alignment Module , proposition du W3C inachevée visant à établir un ensemble commun de propriétés d'alignement à utiliser dans tous les modèles de boîte, présente les éléments suivants:

enter image description here Source: W3C

Vous remarquerez que _justify-self_ et _justify-items_ sont à l'étude ... mais pas pour flexbox .


Je terminerai en réitérant la question principale:

Pourquoi n'y a-t-il pas de propriétés "justifier-éléments" et "justifier-soi"?

575
Michael_B

Méthodes pour aligner les éléments flexibles le long de l'axe principal

Comme indiqué dans la question:

Pour aligner les éléments flexibles le long de l'axe principal, il existe une propriété: justify-content

Pour aligner les éléments flexibles le long de l'axe transversal, il existe trois propriétés: align-content , align-items_ ET _align-self .

La question demande alors:

Pourquoi n'y a-t-il pas de propriétés _justify-items_ et _justify-self_?

Une réponse peut être: car elles ne sont pas nécessaires.

La spécification flexbox fournit deux méthodes pour aligner les éléments flexibles le long de l'axe principal:

  1. La propriété de mot clé _justify-content_, et
  2. auto marges

justifier-contenu

La propriété justify-content aligne les éléments flexibles le long de l'axe principal du conteneur flex.

Il s'applique au conteneur Flex mais n'affecte que les éléments Flex.

Il y a cinq options d'alignement:

  • flex-start ~ Les éléments Flex sont regroupés au début de la ligne.

    enter image description here

  • flex-end ~ Les éléments Flex sont regroupés vers la fin de la ligne.

    enter image description here

  • center ~ Les éléments Flex sont regroupés vers le centre de la ligne.

    enter image description here

  • space-between ~ Les éléments Flex sont espacés régulièrement, le premier élément étant aligné sur un bord du conteneur et le dernier élément sur le bord opposé. Les arêtes utilisées par les premier et dernier éléments dépendent de flex-direction et mode écriture (ltr ou rtl).

    enter image description here

  • space-around ~ Identique à _space-between_ sauf avec des espaces demi-taille aux deux extrémités.

    enter image description here


Marges automatiques

Avec auto margin , les éléments flexibles peuvent être centrés, espacés ou regroupés en sous-groupes.

Contrairement à _justify-content_, qui est appliqué au conteneur flexible, les marges auto s'appliquent aux éléments flexibles.

Ils travaillent en consommant tout l’espace libre dans la direction spécifiée.


Aligner le groupe d'éléments flexibles à droite, mais le premier élément à gauche

Scénario de la question:

  • aligner un groupe d'éléments flexibles à droite (_justify-content: flex-end_) mais faire en sorte que le premier élément s'aligne à gauche (_justify-self: flex-start_)

    Considérons une section d'en-tête avec un groupe d'éléments de navigation et un logo. Avec _justify-self_, le logo peut être aligné à gauche, tandis que les éléments de navigation restent tout à fait à droite, et le tout s’ajuste sans à-coups ("fléchit") à différentes tailles d’écran.

enter image description here

enter image description here


Autres scénarios utiles:

enter image description here

enter image description here

enter image description here


Placez un article flexible dans le coin

Scénario de la question:

  • placer un article flexible dans un coin _.box { align-self: flex-end; justify-self: flex-end; }_

enter image description here


Centrer un article flexible verticalement et horizontalement

enter image description here

_margin: auto_ est une alternative à _justify-content: center_ et _align-items: center_.

Au lieu de ce code sur le conteneur flex:

_.container {
    justify-content: center;
    align-items: center;
}
_

Vous pouvez l’utiliser sur l’article flex:

_.box56 {
    margin: auto;
}
_

Cette alternative est utile lorsque [centrant un élément flexible qui déborde du conteneur] .


Centrer un élément flexible et centrer un deuxième élément flexible entre le premier et le bord

Un conteneur Flex aligne les éléments Flex en répartissant l’espace libre.

Par conséquent, afin de créer un solde égal , afin qu'un élément du milieu puisse être centré dans le conteneur avec un seul élément à côté, un contrepoids doit être introduit.

Dans les exemples ci-dessous, des articles de troisième flex invisible (cases 61 et 68) sont introduits pour équilibrer les "vrais" articles (cases 63 et 66).

enter image description here

enter image description here

Bien sûr, cette méthode n’a rien de bien en termes de sémantique.

Vous pouvez également utiliser un pseudo-élément au lieu d'un élément DOM réel. Ou vous pouvez utiliser le positionnement absolu. Les trois méthodes sont décrites ici: éléments flex centraux et alignés vers le bas

REMARQUE: Les exemples ci-dessus ne fonctionneront - en termes de centrage réel - que lorsque les éléments les plus externes auront la même hauteur/largeur. Si les éléments flexibles ont des longueurs différentes, voir l'exemple suivant.


Centrez un élément flexible lorsque la taille des éléments adjacents varie

Scénario de la question:

  • dans une rangée de trois éléments flexibles, fixez l'élément central au centre du conteneur (_justify-content: center_) et alignez les éléments adjacents sur les bords du conteneur (_justify-self: flex-start_ et _justify-self: flex-end_).

    Notez que les valeurs _space-around_ et _space-between_ sur _justify-content_ ne maintiendront pas l'élément du milieu centré par rapport au conteneur si les éléments adjacents ont des largeurs différentes (- voir la démo ).

Comme indiqué, à moins que tous les éléments flexibles aient une largeur ou une hauteur égales (selon _flex-direction_), l'élément central ne peut pas être véritablement centré. Ce problème constitue un cas solide pour une propriété _justify-self_ (conçue pour gérer la tâche, bien sûr).

_#container {
  display: flex;
  justify-content: space-between;
  background-color: lightyellow;
}
.box {
  height: 50px;
  width: 75px;
  background-color: springgreen;
}
.box1 {
  width: 100px;
}
.box3 {
  width: 200px;
}
#center {
  text-align: center;
  margin-bottom: 5px;
}
#center > span {
  background-color: aqua;
  padding: 2px;
}_
_<div id="center">
  <span>TRUE CENTER</span>
</div>

<div id="container">
  <div class="box box1"></div>
  <div class="box box2"></div>
  <div class="box box3"></div>
</div>

<p>The middle box will be truly centered only if adjacent boxes are equal width.</p>_

Voici deux méthodes pour résoudre ce problème:

Solution n ° 1: Positionnement absolu

La spécification flexbox permet positionnement absolu des éléments flex . Cela permet à l'élément du milieu d'être parfaitement centré quelle que soit la taille de ses frères et sœurs.

N'oubliez pas que, comme tous les éléments à positionnement absolu, les éléments sont supprimés de flux de documents . Cela signifie qu'ils ne prennent pas de place dans le conteneur et peuvent chevaucher leurs frères et soeurs.

Dans les exemples ci-dessous, l'élément central est centré avec le positionnement absolu et les éléments extérieurs restent entrants. Mais la même disposition peut être obtenue de manière inversée: Centrez l'élément du milieu avec _justify-content: center_ et positionnez les éléments les plus à l'extérieur.

enter image description here

Solution n ° 2: Conteneurs Flex imbriqués (pas de positionnement absolu)

_.container {
  display: flex;
}
.box {
  flex: 1;
  display: flex;
  justify-content: center;
}
.box71 > span { margin-right: auto; }
.box73 > span { margin-left: auto;  }

/* non-essential */
.box {
  align-items: center;
  border: 1px solid #ccc;
  background-color: lightgreen;
  height: 40px;
}_
_<div class="container">
  <div class="box box71"><span>71 short</span></div>
  <div class="box box72"><span>72 centered</span></div>
  <div class="box box73"><span>73 loooooooooooooooong</span></div>
</div>_

Voilà comment cela fonctionne:

  • La div de niveau supérieur (_.container_) est un conteneur flexible.
  • Chaque div enfant (_.box_) est maintenant un élément flexible.
  • Chaque élément _.box_ reçoit _flex: 1_ afin de répartir équitablement l'espace conteneur.
  • Désormais, les éléments occupent tout l’espace de la ligne et ont la même largeur.
  • Faites de chaque article un conteneur flexible (imbriqué) et ajoutez _justify-content: center_.
  • Maintenant, chaque élément span est un élément flex centré.
  • Utilisez les marges auto flexibles pour déplacer les spans extérieurs vers la gauche et vers la droite.

Vous pouvez également renoncer à _justify-content_ et utiliser exclusivement les marges auto.

Mais _justify-content_ peut fonctionner ici car les marges auto sont toujours prioritaires. De la spec:

8.1. Alignement sur les marges auto

Avant l'alignement via _justify-content_ et _align-self_, tout espace libre positif est distribué aux marges automatiques dans cette dimension.


justifier-contenu: espace-même (concept)

Pour revenir à justify-content pendant une minute, voici une idée pour une option supplémentaire.

  • space-same ~ Un hybride de _space-between_ et _space-around_. Les éléments flexibles sont régulièrement espacés (comme _space-between_), à la place d'espaces demi-taille aux deux extrémités (comme _space-around_), il y a des espaces en taille réelle aux deux extrémités.

Cet agencement peut être réalisé avec ::before et ::after pseudo-éléments sur le conteneur flex.

enter image description here

(crédit: @ oriol pour le code et @ crl pour l'étiquette)

PDATE: Les navigateurs ont commencé à implémenter space-evenly, ce qui permet de réaliser ce qui précède. Voir ce post pour plus de détails: Espace égal entre les éléments flexibles


PLAYGROUND (inclut le code pour tous les exemples ci-dessus)

1074
Michael_B

Je sais que ce n’est pas une réponse, mais j’aimerais apporter ma contribution à ce sujet. Ce serait bien s'ils pouvaient publier justify-self pour flexbox afin de le rendre vraiment flexible.

Je suis convaincu que lorsqu'il y a plusieurs éléments sur l'axe, le moyen le plus logique de se comporter de justify-self est de s'aligner sur ses voisins les plus proches (ou Edge), comme illustré ci-dessous.

J'espère sincèrement que le W3C en prendra bonne note et l'examinera au moins. =)

enter image description here

De cette façon, vous pouvez avoir un article véritablement centré, quelle que soit la taille des cases gauche et droite. Lorsque l'une des boîtes atteint le point de la boîte centrale, il suffit simplement de la pousser jusqu'à ce qu'il n'y ait plus d'espace à distribuer.

enter image description here

La facilité de création de superbes mises en page est infinie, jetez un coup d'œil à cet exemple "complexe".

enter image description here

119
Mark

Cela a été demandé sur la liste de style www, et Tab Atkins (éditeur de spécifications) a fourni une réponse expliquant pourquoi . Je vais élaborer un peu là-dessus.

Pour commencer, supposons tout d'abord que notre conteneur flex est composé d'une seule ligne (flex-wrap: nowrap). Dans ce cas, il existe clairement une différence d'alignement entre l'axe principal et l'axe transversal: plusieurs éléments sont empilés dans l'axe principal, mais un seul élément est empilé dans l'axe transversal. Il est donc logique d’avoir un "align-self" personnalisable par élément dans l’axe transversal (puisque chaque élément est aligné séparément), alors qu’il n’a pas de sens dans l’axe principal (car, le les articles sont alignés collectivement).

Pour les flexbox multilignes, la même logique s'applique à chaque "ligne flex". Dans une ligne donnée, les éléments sont alignés individuellement dans l'axe transversal (puisqu'il n'y a qu'un seul élément par ligne, dans l'axe transversal), par opposition à collectivement dans l'axe principal.


Voici une autre façon de le formuler: ainsi, toutes les propriétés des propriétés *-self et *-content expliquent comment répartir un espace supplémentaire autour d'objets. Mais la différence principale est que les versions *-self sont destinées aux cas où ne contient qu'une seule chose dans cet axe , et les versions *-content sont destinées aux cas où il existe potentiellement beaucoup de choses dans cet axe . Les scénarios "une chose contre plusieurs choses" correspondent à différents types de problèmes. Ils ont donc différents types d'options disponibles. Par exemple, les valeurs space-around/space-between ont un sens pour *-content, mais pas pour *-self.

SO: Dans l'axe principal d'une flexbox, il y a beaucoup de choses pour répartir l'espace. Donc, une propriété *-content a un sens ici, mais pas une propriété *-self.

En revanche, dans l’axe transversal, nous avons à la fois une propriété *-self et une *-content. L’un détermine la manière dont nous répartirons l’espace autour des nombreuses lignes flexibles (align-content), tandis que l’autre (align-self) détermine la répartition de l’espace individuel éléments flex dans l’axe transversal, au sein d’une même ligne flex.

(J'ignore les propriétés *-items ici, car elles établissent simplement les valeurs par défaut pour *-self.)

18
dholbert

Je sais que cela n'utilise pas flexbox, mais pour le cas d'utilisation simple de trois éléments (un à gauche, un au centre, un à droite), ceci peut être facilement réalisé en utilisant display: grid sur le parent, grid-area: 1/1/1/1; sur les enfants et justify-self pour le positionnement de ces enfants.

<div style="border: 1px solid red; display: grid; width: 100px; height: 25px;">
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: left;"></div>
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: center;"></div>
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: right;"></div>
</div>
0
Venryx

Il y a justify-self, mais dans Chrome Canary, pas dans Chrome version stable. Il y a même justify-items:

enter image description here

Mais pour autant que je sache, ces propriétés ne fonctionnent pas non plus. Il est donc probable que Google l’a enregistré à l’avance pour les futures versions CSS. Je ne peux qu’espérer qu’ils ajouteront bientôt les propriétés.

0
Green