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

678

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

entrez la description de l'image ici                                                                                                                                                    Source: 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 flexible.

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

/* 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 point en décrivant comment le travail des axes est qu'il ne semble y avoir rien de spécial dans l'une ou l'autre direction. Axe principal, axe transversal, ils sont tous deux égaux en importance et flex-directionfacilitent les allers-retours.

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

Pourquoi align-contentet align-itemsconsolidé en une seule propriété pour l'axe principal?

Pourquoi l'axe principal n'obtient-il pas de justify-selfpropriété?


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

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

  • création d'un groupe d'éléments flexibles align-right ( justify-content: flex-end) mais le premier élément s'aligne left ( justify-self: flex-start)

    Considérez une section d'en-tête avec un groupe d'éléments de navigation et un logo. Avec justify-selfle logo pourrait être aligné à gauche tandis que les éléments de navigation restent à l'extrême droite, et le tout s'ajuste en douceur ("fléchit") à différentes tailles d'écran.

  • dans une rangée de trois éléments flexibles, fixez l'élément du milieu au centre du conteneur ( justify-content: center) et alignez les éléments adjacents sur les bords du conteneur ( justify-self: flex-startet justify-self: flex-end).

    Notez que les valeurs space-aroundet space-betweensur la justify-contentpropriété ne gardera pas l'élément Centré au milieu autour du récipient si les éléments adjacents ont des largeurs différentes.

Version jsFiddle


Au moment d'écrire ces lignes , il n'y a aucune mention de justify-selfou justify-itemsdans la spécification flexbox .

Cependant, dans le module d'alignement de boîtes CSS , qui est la proposition inachevée du W3C d'établir un ensemble commun de propriétés d'alignement à utiliser sur tous les modèles de boîtes, il y a ceci:

entrez la description de l'image ici                                                                                                                                                    Source: W3C

Vous le remarquerez justify-selfet justify-itemsêtes envisagé ... mais pas pour la flexbox .


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

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

Michael Benjamin
la source
4
Comment vous attendriez-vous justify-selfà travailler pour un article flexible? Supposons que vous ayez des éléments a, b, c, d avec un espace supplémentaire à distribuer autour d'eux, et que le conteneur flexible en dispose justify-content: space-between, de sorte qu'ils finissent comme | abcd |. Qu'est-ce que cela signifierait d'ajouter par exemple justify-self: centerou «justifier-soi: flex-end» juste pour l'élément «b»? Où vous attendriez-vous à ce qu'il aille? (Je vois quelques démos dans l'une des réponses ici, mais je ne vois pas de manière claire que cela fonctionnerait en général.)
dholbert
(Alternativement: supposons que nous l'avons fait justify-content: flex-start, donc les éléments sont encombrés au début comme | abcd |. Que vous attendriez-vous à ce que cela se justify-self: [anything]
produise
1
@dholbert, vous avez écrit: Comment vous attendriez-vous justify-selfà travailler pour un élément flexible? Je dirais pas si différemment que les automarges fonctionnent déjà sur les éléments flexibles. Dans votre deuxième exemple, l' justify-self: flex-endélément d le déplacerait vers le bord éloigné. Ce serait en soi une grande fonctionnalité, ce que les automarges peuvent déjà faire. J'ai posté une réponse avec une démonstration.
Michael Benjamin
2
Je vois de plus pour la plupart des cas d' utilisation ici, et les cas d' utilisation sont grands - mais le plus délicat est de savoir comment cette chausse - pied dans la réelle manière justify-contentet justify-selfsont spécifiés, de sorte que les cas avec les conflits (comme les scénarios je leur ai demandé) sont clairement et sensiblement définis. Comme je l'ai noté dans ma réponse ici, il {justify|align}-selfs'agit d'aligner les éléments dans une boîte plus grande qui est dimensionnée indépendamment de la {justify|align}-selfvaleur - et il n'y a pas une telle boîte, dans l'axe principal, pour un élément flexible à aligner.
dholbert
1
RE "pas différent des marges automatiques" - je demandais en fait comment vous imaginez justify-selfet justify-contentinteragiriez, en cas de conflit (comme les scénarios que j'ai exposés). Marges automatiques ne suffit pas d' interagir avec justify-contentdu tout - ils volent tout l'espace d'emballage avant justify-contentobtient une chance de l' utiliser. Ainsi, les marges automatiques ne sont pas vraiment un bon analogue pour savoir comment cela fonctionnerait.
dholbert

Réponses:

1255

Méthodes d'alignement des é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-itemsetalign-self .

La question demande alors:

Pourquoi n'y a-t-il pas justify-itemsjustify-self propriétés et ?

Une réponse peut être: parce qu'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. le justify-content propriété du mot clé, et
  2. auto marges

justifier-contenu

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

Il est appliqué au conteneur flexible mais n'affecte que les éléments flexibles.

Il existe cinq options d'alignement:

  • flex-start ~ Les articles flexibles sont emballés vers le début de la ligne.

    entrez la description de l'image ici

  • flex-end ~ Les articles flexibles sont emballés vers la fin de la ligne.

    entrez la description de l'image ici

  • center ~ Les articles flexibles sont emballés vers le centre de la ligne.

    entrez la description de l'image ici

  • space-between~ Les éléments flexibles sont régulièrement espacés, le premier élément étant aligné sur un bord du conteneur et le dernier élément aligné sur le bord opposé. Les bords utilisés par les premier et dernier éléments dépendent flex-directionet mode d'écriture ( ltrou rtl).

    entrez la description de l'image ici

  • space-around~ Identique space-betweensauf avec des espaces demi-taille aux deux extrémités.

    entrez la description de l'image ici


Marges automatiques

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

Contrairement à justify-contentce qui est appliqué au conteneur flexible,auto marges vont aux éléments flexibles.

Ils fonctionnent 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:

  • création d'un groupe d'éléments flexibles align-right ( justify-content: flex-end) mais le premier élément s'aligne left ( justify-self: flex-start)

    Considérez une section d'en-tête avec un groupe d'éléments de navigation et un logo. Avec justify-selfle logo pourrait être aligné à gauche tandis que les éléments de navigation restent à l'extrême droite, et le tout s'ajuste en douceur ("fléchit") à différentes tailles d'écran.

entrez la description de l'image ici

entrez la description de l'image ici


Autres scénarios utiles:

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici


Placer un élément flexible dans le coin

Scénario de la question:

  • placer un élément flexible dans un coin .box { align-self: flex-end; justify-self: flex-end; }

entrez la description de l'image ici


Centrer un élément flexible verticalement et horizontalement

entrez la description de l'image ici

margin: autoest une alternative à justify-content: centeretalign-items: center .

Au lieu de ce code sur le conteneur flex:

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

Vous pouvez l'utiliser sur l'élément flexible:

.box56 {
    margin: auto;
}

Cette alternative est utile lors du centrage d'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 flexible aligne les articles flexibles en distribuant de l'espace libre.

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

Dans les exemples ci-dessous, des troisièmes éléments flexibles invisibles (cases 61 et 68) sont introduits pour équilibrer les «vrais» éléments (cases 63 et 66).

entrez la description de l'image ici

entrez la description de l'image ici

Bien sûr, cette méthode n'a rien de génial en termes de sémantique.

Alternativement, vous pouvez utiliser un pseudo-élément au lieu d'un élément DOM réel. Ou vous pouvez utiliser un positionnement absolu. Les trois méthodes sont traitées ici: Éléments flexibles centrés et alignés en bas

REMARQUE: Les exemples ci-dessus ne fonctionneront - en termes de centrage réel - que lorsque les éléments les plus externes sont égaux en hauteur / largeur. Lorsque les éléments flexibles sont de longueurs différentes, voir l'exemple suivant.


Centrer un élément flexible lorsque les éléments adjacents varient en taille

Scénario de la question:

  • dans une rangée de trois éléments flexibles, fixez l'élément du milieu au centre du conteneur ( justify-content: center) et alignez les éléments adjacents sur les bords du conteneur ( justify-self: flex-startet justify-self: flex-end).

    Notez que les valeurs space-aroundet space-betweensur la justify-contentpropriété ne gardera pas l'élément Centré au milieu 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 soient de largeur ou de hauteur égales (selon flex-direction), l'élément central ne peut pas être vraiment centré. Ce problème constitue un argument solide pour une justify-selfpropriété (conçue pour gérer la tâche, bien sûr).

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

Solution n ° 1: positionnement absolu

La spécification flexbox permet un positionnement absolu des éléments flexibles . 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 positionnés de manière absolue, les éléments sont supprimés du flux de documents . Cela signifie qu'ils ne prennent pas de place dans le conteneur et peuvent chevaucher leurs frères et sœurs.

Dans les exemples ci-dessous, l'élément central est centré avec un positionnement absolu et les éléments externes restent en flux. Mais la même mise en page peut être réalisée de manière inverse: Centrez l'élément du milieu avec justify-content: centeret positionnez absolument les éléments extérieurs.

entrez la description de l'image ici

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>

Voici comment ça fonctionne:

  • Le div de niveau supérieur (.container ) est un conteneur flexible.
  • Chaque div enfant ( .box) est désormais un élément flexible.
  • Chaque .boxarticle est donné flex: 1afin de répartir également l'espace du conteneur.
  • Maintenant, les éléments consomment tout l'espace de la ligne et sont de largeur égale.
  • Faites de chaque élément un conteneur flexible (imbriqué) et ajoutez-le justify-content: center.
  • Maintenant, chaque spanélément est un élément flexible centré.
  • Utilisez des automarges flexibles pour décaler les extrémités externes vers la spangauche et la droite.

Vous pouvez également renoncer justify-contentet utiliser des automarges exclusivement.

Mais justify-contentpeut fonctionner ici car les automarges ont toujours la priorité. De la spécification:

8.1. Alignement sur les auto marges

Avant l'alignement via justify-contentet align-self, tout espace libre positif est distribué aux marges automatiques dans cette dimension.


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

Pour revenir à justify-contentune minute, voici une idée pour une option de plus.

  • space-same~ Un hybride de space-betweenet space-around. Les éléments flexibles sont régulièrement espacés (comme space-between), sauf qu'au lieu d'espaces demi-taille aux deux extrémités (comme space-around), il y a des espaces pleine taille aux deux extrémités.

Cette disposition peut être réalisé avec ::beforeet ::afterpseudo-éléments sur le conteneur flexible.

entrez la description de l'image ici

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

MISE À JOUR: Les navigateurs ont commencé à mettre en œuvre space-evenly, ce qui accomplit ce qui précède. Voir cet article pour plus de détails: Espace égal entre les éléments flexibles


AIRE DE JEUX (inclut le code pour tous les exemples ci-dessus)

Michael Benjamin
la source
1
La réponse ci - dessus couvre l' axe principal , justify-contentet les automarges. Pour l'autre côté de la médaille - l' axe croix , align-items, align-selfet align-content- voir ce post: stackoverflow.com/q/42613359/3597276
Michael Benjamin
4
@MarkW, vous plaidez pour la justify-selfpropriété ... les automarges sont utiles, mais justify-self: centerseraient idéales. La façon de résoudre le problème que vous avez présenté serait de créer des doublons invisibles du côté opposé. Voir ma réponse ici: stackoverflow.com/q/38948102/3597276
Michael Benjamin
5
Votre space-sameconcept est une chose réelle maintenant. Il s'appelle space-evenly, mais il n'est pris en charge que par Firefox pour le moment: developer.mozilla.org/en-US/docs/Web/CSS/justify-content
benface
1
@benface, oui, vous avez raison. Merci d'avoir fait remarquer cela. J'ai en fait écrit space-evenlydans d'autres réponses: stackoverflow.com/q/45134400/3597276
Michael Benjamin
1
En fait, space-evenly était pris en charge dans Chrome 57-60, mais uniquement pour la disposition de la grille. C'était un bug qui a été corrigé, et depuis Chrome 61, il est également pris en charge pour Flexbox. En outre, il y a la façon d'imiter sans pseudo-éléments: .item { margin-right: auto } .item:first-child { margin-left: auto }.
Ilya Streltsyn
155

Je sais que ce n'est pas une réponse, mais j'aimerais contribuer à cette question pour ce qu'elle vaut. Ce serait formidable s'ils pouvaient libérer justify-selfFlexbox pour le rendre vraiment flexible.

Je pense que lorsqu'il y a plusieurs éléments sur l'axe, la manière la plus logique de justify-selfse comporter est de s'aligner sur ses voisins (ou bords) les plus proches, comme illustré ci-dessous.

J'espère vraiment que le W3C en prend note et y réfléchira au moins. =)

entrez la description de l'image ici

De cette façon, vous pouvez avoir un élément qui est vraiment 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, elle la poussera simplement jusqu'à ce qu'il n'y ait plus d'espace à distribuer.

entrez la description de l'image ici

La facilité de faire des mises en page impressionnantes est infinie, jetez un oeil à cet exemple "complexe".

entrez la description de l'image ici

marque
la source
12
@Mark c'est incroyable! Merci d'avoir pris le temps de rédiger ceci. J'espère que cela ne vous dérange pas, mais je l'ai soumis ici: discourse.wicg.io/t/flexbox-justify-self-property/1146
Zaqx
1
@Zaqx bien sûr, plus il y a d'exposition, mieux c'est. J'espère sincèrement qu'ils trouveront un moyen de faire de cette réalité, j'adorerais me salir les mains.
Mark
1
Bonjour Mark, @Zaqx, j'ai posté une réponse qui peut couvrir certains des cas d'utilisation mentionnés dans cette réponse. J'ai découvert que beaucoup peut encore être fait dans l'axe principal sans avoir besoin de justify-selfet justify-items.
Michael Benjamin
3
@Michael_B Heureux d'en savoir plus sur la flexbox et appréciez d'avoir pris le temps de formater vos notes en réponse. Marge: auto est en effet cool (même si vous trouverez que les navigateurs qui ont implémenté les versions 2009 et 2012 de la spécification flexbox n'ont pas de fonctionnalité équivalente qui réduit considérablement la possibilité de l'utiliser sur un site de production). Cependant, même avec les navigateurs qui prennent en charge margin: auto, le cas d'utilisation principal ici d'un élément qui est centré par rapport à son conteneur alors que l'espace existe est toujours impossible sans une propriété de justification ou similaire.
Zaqx
1
@Zaqx, merci pour les commentaires. Et oui, je suis d'accord avec vous, les automarges ne sont pas un substitut complet justify-self. J'ai pris soin de formuler mon commentaire précédent en disant que les automarges couvriront certains des cas d'utilisation . Comme vous l'avez noté, il ne peut pas centrer un élément en place lorsque les éléments adjacents sont de tailles différentes. Cependant, il offre plus d'options pour aligner les éléments flexibles. Quand j'ai commencé à apprendre sur Flexbox, je pensais justify-contentque les éléments d'espacement invisibles étaient le seul moyen.
Michael Benjamin
20

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 en parler un peu ici.

Pour commencer, supposons d'abord que notre conteneur flexible est à une seule ligne (flex-wrap: nowrap ). Dans ce cas, il y a clairement une différence d'alignement entre l'axe principal et l'axe transversal - il y a plusieurs éléments empilés dans l'axe principal, mais un seul élément 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, seul), alors qu'il n'a pas de sens dans l'axe principal (car là, le les éléments sont alignés collectivement).

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


Voici une autre façon de le formuler: ainsi, toutes les propriétés *-selfet *-contentconcernent la répartition de l'espace supplémentaire autour des choses. Mais la principale différence est que les *-selfversions sont pour les cas où il n'y a qu'une seule chose dans cet axe , et les *-contentversions sont pour quand il y a potentiellement beaucoup de choses dans cet axe . Les scénarios à une seule chose ou à plusieurs choses sont différents types de problèmes, et ils ont donc différents types d'options disponibles - par exemple, les valeurs space-around/ ont space-betweenun 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 autour. Une *-contentpropriété a donc un sens, mais pas un*-self propriété.

En revanche, dans l'axe transversal, nous avons à la fois une *-selfet une *-contentpropriété. L'un détermine comment nous allons répartir l'espace autour des nombreuses lignes flexibles ( align-content), tandis que l'autre ( align-self) détermine comment répartir l'espace autour des éléments flex individuels dans l'axe transversal, au sein d'une ligne flexible donnée.

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

dholbert
la source
1
Je comprends que cela justify-selfpourrait être un problème sur un axe avec plusieurs éléments plutôt qu'un seul. Cependant, j'espère vraiment qu'ils approfondiront la question, dans une situation à éléments multiples, comment se justify-selfcomporterait-il, car il y a des situations où cela pourrait être vraiment utile. Par exemple ( stackoverflow.com/questions/32378953/… ).
Mark
Belle trouvaille sur cette liste de diffusion. Essayer d'envelopper ma tête autour de lui, car je vois toujours de bonnes possibilités de cas d'utilisation pour justify-self.
Michael Benjamin
J'ai ajouté un peu plus de précisions, expliquant comment il *-selfs'agit de cas où nous n'avons qu'une seule chose à aligner, alors qu'il *-contents'agit de cas où nous avons beaucoup de choses à aligner. Est-ce que cela le rend un peu plus clair?
dholbert
Oui, c'est plus clair. J'apprécie l'explication. Mais cela semble se résumer à une simple préférence des auteurs de la spécification, et non à un besoin particulier basé sur la logique. De la liste de diffusion que vous avez référencée : Les propriétés * -self ne fonctionnent que si l'enfant est tout seul dans cet axe. Pourquoi? Cela ne semble pas être nécessaire. C'est une décision arbitraire. Une préférence. En fait, les automarges, qui font également partie de la spécification, permettent l'alignement * -self avec plusieurs éléments de la ligne. Aucune raison claire pour laquelle les propriétés des mots clés ne le peuvent pas également.
Michael Benjamin
1

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), cela peut être accompli facilement en utilisant display: gridle parent, grid-area: 1/1/1/1;les enfants et le justify-selfpositionnement 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>

Venryx
la source
Merci pour la réponse, mais cela ne répond pas vraiment à la question. En outre, il existe un moyen plus simple de réaliser votre mise en page: jsfiddle.net/fga89m2o
Michael Benjamin
0

Je viens de trouver ma propre solution à ce problème, ou du moins mon problème.
J'utilisais justify-content: space-aroundau lieu dejustify-content: space-between; .

De cette façon, les éléments finaux resteront en haut et en bas, et vous pourriez avoir des marges personnalisées si vous le souhaitez.

Leif Messinger LOAF
la source