Nel CSS Flexbox, perché non ci sono proprietà "justify-items" e "justify-self"?


678

Considera l'asse principale e l'asse trasversale di un contenitore flessibile:

inserisci qui la descrizione dell'immagine                                                                                                                                                    Fonte: W3C

Per allineare gli elementi flessibili lungo l'asse principale esiste una proprietà:

Per allineare gli elementi flessibili lungo l'asse trasversale ci sono tre proprietà:

Nell'immagine sopra, l'asse principale è orizzontale e l'asse trasversale è verticale. Queste sono le direzioni predefinite di un contenitore flessibile.

Tuttavia, queste direzioni possono essere facilmente scambiate con la flex-directionproprietà.

/* 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'asse trasversale è sempre perpendicolare all'asse principale.)

Il mio punto nel descrivere come il lavoro degli assi è che non sembra esserci nulla di speciale in nessuna delle due direzioni. Asse principale, asse trasversale, sono entrambi uguali in termini di importanza e flex-directionfacilita il passaggio avanti e indietro.

Quindi perché l'asse trasversale ottiene due proprietà di allineamento aggiuntive?

Perché sono align-contente align-itemsconsolidati in una proprietà per l'asse principale?

Perché l'asse principale non ottiene una justify-selfproprietà?


Scenari in cui queste proprietà sarebbero utili:

  • posizionando un oggetto flessibile nell'angolo del contenitore flessibile
    #box3 { align-self: flex-end; justify-self: flex-end; }

  • facendo allineare un gruppo di elementi flessibili a destra ( justify-content: flex-end) ma allineare il primo elemento a sinistra ( justify-self: flex-start)

    Considera una sezione di intestazione con un gruppo di elementi di navigazione e un logo. Con justify-selfil logo potrebbe essere allineato a sinistra mentre gli elementi di navigazione rimangono all'estrema destra e il tutto si regola senza problemi ("si flette") a dimensioni dello schermo diverse.

  • in una fila di tre oggetti flessibili, applicare l'elemento centrale al centro del contenitore ( justify-content: center) e allineare gli oggetti adiacenti ai bordi del contenitore ( justify-self: flex-starte justify-self: flex-end).

    Si noti che i valori space-arounde space-betweensulla justify-contentproprietà non manterranno l'elemento centrale centrato sul contenitore se gli elementi adiacenti hanno larghezze diverse.

Versione jsFiddle


Al momento della stesura di questo documento, non è menzionato justify-selfjustify-itemsnelle specifiche del flexbox .

Tuttavia, nel CSS Box Alignment Module , che è la proposta incompiuta del W3C di stabilire un insieme comune di proprietà di allineamento da utilizzare su tutti i modelli di box, c'è questo:

inserisci qui la descrizione dell'immagine                                                                                                                                                    Fonte: W3C

Lo noterai justify-selfe verraijustify-items considerato ... ma non per Flexbox .


Finirò ripetendo la domanda principale:

Perché non ci sono proprietà "giustificare-elementi" e "giustificare-sé"?


4
Come ti aspetti justify-selfdi lavorare per un articolo flessibile? Supponiamo di avere oggetti a, b, c, d con spazio extra da distribuire attorno a loro, e il contenitore flessibile abbia justify-content: space-between, quindi finiscono come | abcd |. Cosa significherebbe aggiungere, ad esempio, justify-self: centero 'giustificare-sé: fine flessibile' solo all'elemento 'b' lì? Dove ti aspetteresti che vada? (Vedo alcune demo in una delle risposte qui, ma non vedo un modo chiaro che funzionerebbe in generale.)
dholbert,

(In alternativa: supponiamo di averlo justify-content: flex-start, quindi all'inizio gli oggetti sono affollati come | abcd |. Cosa ti aspetteresti che faccia, se metti justify-self: [anything]l'oggetto 'b' lì?)
dholbert,

1
@dholbert, hai scritto: come ti aspetti justify-selfdi lavorare per un oggetto flessibile? Direi non diversamente dai automargini che funzionano già su articoli flessibili. Nel tuo secondo esempio, justify-self: flex-endsull'elemento d lo sposteresti sul bordo lontano. Questa di per sé sarebbe una grande caratteristica, che i automargini possono già fare. Ho pubblicato una risposta con una dimostrazione.
Michael Benjamin,

2
Per lo più vedo più casi d'uso qui, e casi d'uso sono fantastici - ma la parte difficile è come calzare questo nel modo effettivojustify-content e justify-selfspecificato, in modo che i casi con conflitti (come gli scenari di cui ho chiesto) sono chiaramente e sensibilmente definiti. Come ho notato nella mia risposta qui, si {justify|align}-selftratta di allineare gli oggetti all'interno di una scatola più grande che è dimensionata indipendentemente dal {justify|align}-selfvalore - e non esiste una scatola simile, nell'asse principale, in cui un oggetto flessibile possa essere allineato.
dholbert il

1
RE "non diverso dai margini automatici" - In realtà stavo chiedendo come immagini justify-selfe come justify-contentinteragiresti, nei casi in cui sono in conflitto (come gli scenari che ho definito). I margini automatici semplicemente non interagiscono justify-contentaffatto: rubano tutto lo spazio di imballaggio prima che abbiano la justify-contentpossibilità di usarlo. Quindi, i margini automatici non sono davvero un buon analogo per come funzionerebbe.
dholbert il

Risposte:


1255

Metodi per allineare gli articoli flessibili lungo l'asse principale

Come indicato nella domanda:

Per allineare gli elementi flessibili lungo l'asse principale esiste una proprietà: justify-content

Per elementi flessibili allineati lungo l'asse trasversale ci sono tre proprietà: align-content, align-itemsealign-self .

La domanda quindi pone:

Perché non ci sono justify-itemse justify-selfproprietà?

Una risposta potrebbe essere: perché non sono necessari.

Le specifiche del flexbox forniscono due metodi per allineare gli articoli flessibili lungo l'asse principale:

  1. La justify-contentproprietà della parola chiave e
  2. auto margini

justify-contenuti

La justify-contentproprietà allinea gli elementi flessibili lungo l'asse principale del contenitore flessibile.

Viene applicato al contenitore flessibile ma interessa solo gli articoli flessibili.

Esistono cinque opzioni di allineamento:

  • flex-start ~ Gli articoli Flex vengono imballati all'inizio della riga.

    inserisci qui la descrizione dell'immagine

  • flex-end ~ Gli articoli Flex vengono imballati verso la fine della linea.

    inserisci qui la descrizione dell'immagine

  • center ~ Gli articoli flessibili sono imballati verso il centro della linea.

    inserisci qui la descrizione dell'immagine

  • space-between~ Gli oggetti flessibili sono distribuiti uniformemente, con il primo oggetto allineato a un bordo del contenitore e l'ultimo oggetto allineato al bordo opposto. I bordi utilizzati dai primi e ultimi dipende flex-directione modalità di scrittura ( ltro rtl).

    inserisci qui la descrizione dell'immagine

  • space-around~ Come per gli space-betweenspazi di mezzo formato su entrambe le estremità.

    inserisci qui la descrizione dell'immagine


Margini automatici

Con i automargini , gli oggetti flessibili possono essere centrati, distanziati o raggruppati in sottogruppi.

Diversamente justify-content, che viene applicato al contenitore flessibile, i automargini vanno sugli oggetti flessibili.

Funzionano consumando tutto lo spazio libero nella direzione specificata.


Allinea il gruppo di elementi flessibili a destra, ma il primo elemento a sinistra

Scenario della domanda:

  • facendo allineare un gruppo di elementi flessibili a destra ( justify-content: flex-end) ma allineare il primo elemento a sinistra ( justify-self: flex-start)

    Considera una sezione di intestazione con un gruppo di elementi di navigazione e un logo. Con justify-selfil logo potrebbe essere allineato a sinistra mentre gli elementi di navigazione rimangono all'estrema destra e il tutto si regola senza problemi ("si flette") a dimensioni dello schermo diverse.

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


Altri scenari utili:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


Posiziona un oggetto flessibile nell'angolo

Scenario della domanda:

  • posizionando un oggetto flessibile in un angolo .box { align-self: flex-end; justify-self: flex-end; }

inserisci qui la descrizione dell'immagine


Centra un oggetto flessibile in verticale e in orizzontale

inserisci qui la descrizione dell'immagine

margin: autoè un'alternativa a justify-content: centere align-items: center.

Invece di questo codice sul contenitore flessibile:

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

Puoi usarlo sull'elemento flessibile:

.box56 {
    margin: auto;
}

Questa alternativa è utile quando si centra un elemento flessibile che trabocca dal contenitore .


Centra un oggetto flessibile e centra un secondo oggetto flessibile tra il primo e il bordo

Un contenitore flessibile allinea gli oggetti flessibili distribuendo spazio libero.

Quindi, al fine di creare un equilibrio uguale , in modo che un elemento intermedio possa essere centrato nel contenitore con un singolo articolo a fianco, deve essere introdotto un contrappeso.

Negli esempi seguenti, vengono introdotti i terzi oggetti flex invisibili (riquadri 61 e 68) per bilanciare gli elementi "reali" (riquadri 63 e 66).

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

Naturalmente, questo metodo non è eccezionale in termini di semantica.

In alternativa, puoi usare uno pseudo-elemento invece di un vero elemento DOM. Oppure puoi usare il posizionamento assoluto. Tutti e tre i metodi sono trattati qui: oggetti flessibili al centro e allineati in basso

NOTA: gli esempi sopra funzionano solo in termini di centraggio vero - quando gli elementi più esterni sono uguali altezza / larghezza. Quando gli articoli flessibili hanno lunghezze diverse, vedere l'esempio seguente.


Centra un oggetto flessibile quando gli oggetti adiacenti hanno dimensioni variabili

Scenario della domanda:

  • in una fila di tre oggetti flessibili, applicare l'elemento centrale al centro del contenitore ( justify-content: center) e allineare gli oggetti adiacenti ai bordi del contenitore ( justify-self: flex-starte justify-self: flex-end).

    Si noti che i valori space-arounde space-betweensulla justify-contentproprietà non manterranno centrato l'elemento centrale rispetto al contenitore se gli oggetti adiacenti hanno larghezze diverse ( vedere la demo ).

Come notato, a meno che tutti gli oggetti flessibili flex-directionnon abbiano la stessa larghezza o altezza (a seconda di ), l'elemento centrale non può essere veramente centrato. Questo problema è un valido esempio per una justify-selfproprietà (progettata per gestire l'attività, ovviamente).

Ecco due metodi per risolvere questo problema:

Soluzione n. 1: posizionamento assoluto

Le specifiche del flexbox consentono il posizionamento assoluto degli articoli flessibili . Ciò consente di centrare perfettamente l'elemento centrale indipendentemente dalle dimensioni dei suoi fratelli.

Tieni presente che, come tutti gli elementi posizionati in modo assoluto, gli elementi vengono rimossi dal flusso del documento . Ciò significa che non occupano spazio nel contenitore e possono sovrapporsi ai loro fratelli.

Negli esempi seguenti, l'elemento centrale è centrato con posizionamento assoluto e gli elementi esterni rimangono in-flow. Ma lo stesso layout può essere ottenuto al contrario: centrare l'elemento centrale con justify-content: centere posizionare assolutamente gli elementi esterni.

inserisci qui la descrizione dell'immagine

Soluzione n. 2: contenitori Flex nidificati (nessun posizionamento assoluto)

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

Ecco come funziona:

  • Il div ( .container) di livello superiore è un contenitore flessibile.
  • Ogni div ( .box) figlio ora è un oggetto flessibile.
  • Ogni .boxarticolo viene fornito flex: 1per distribuire equamente lo spazio contenitore.
  • Ora gli oggetti stanno consumando tutto lo spazio nella riga e hanno la stessa larghezza.
  • Trasforma ogni oggetto in un contenitore flessibile (nidificato) e aggiungi justify-content: center.
  • Ora ogni spanelemento è un oggetto flessibile centrato.
  • Utilizzare i automargini di flessione per spostare l'esterno a spansinistra e a destra.

È inoltre possibile rinunciare justify-contente utilizzare autoesclusivamente i margini.

Ma justify-contentpuò funzionare qui perché i automargini hanno sempre la priorità. Dalle specifiche:

8.1. Allineando con i auto margini

Prima dell'allineamento tramite justify-contente align-self, qualsiasi spazio libero positivo viene distribuito ai margini automatici in quella dimensione.


justify-content: space-same (concept)

Tornando a justify-contentper un minuto, ecco un'idea per un'altra opzione.

  • space-same~ Un ibrido di space-betweene space-around. Gli oggetti Flex sono equidistanti (come space-between), tranne che per gli spazi di mezza dimensione su entrambe le estremità (come space-around), ci sono spazi di dimensioni normali su entrambe le estremità.

Questo layout può essere realizzato con ::beforee ::afterpseudo-elementi sul contenitore flessibile.

inserisci qui la descrizione dell'immagine

(credito: @oriol per il codice e @crl per l'etichetta)

AGGIORNAMENTO: i browser hanno iniziato l'implementazione space-evenly, il che realizza quanto sopra. Vedi questo post per i dettagli: uguale spazio tra gli oggetti flessibili


PLAYGROUND (include il codice per tutti gli esempi sopra)


1
La risposta sopra copre il principale asse , justify-contente automargini. Per l'altro lato della medaglia - l' asse trasversale , align-items, align-selfe align-content- vedi questo post: stackoverflow.com/q/42613359/3597276
Michael Benjamin

4
@MarkW, stai affermando la justify-selfproprietà ... i automargini sono utili, ma justify-self: centersarebbe l'ideale. Il modo per risolvere il problema che hai presentato sarebbe quello di creare oggetti duplicati invisibili sul lato opposto. Vedi la mia risposta qui: stackoverflow.com/q/38948102/3597276
Michael Benjamin

5
Il tuo space-sameconcetto è una cosa reale ora. Si chiama space-evenly, ma al momento è supportato solo da Firefox: developer.mozilla.org/en-US/docs/Web/CSS/justify-content
benface

1
@benface, Sì, hai ragione. Grazie per la segnalazione. In realtà ho scritto space-evenlyin altre risposte: stackoverflow.com/q/45134400/3597276
Michael Benjamin,

1
In effetti, space-evenly era supportato in Chrome 57-60, ma solo per il layout Grid. È stato corretto un bug, e dal momento che Chrome 61 è supportato anche per Flexbox. Inoltre, c'è il modo di emulare senza pseudo-elementi: .item { margin-right: auto } .item:first-child { margin-left: auto }.
Ilya Streltsyn,

155

So che questa non è una risposta, ma mi piacerebbe contribuire a questo argomento per quello che vale. Sarebbe bello se potessero rilasciare justify-selfper flexbox per renderlo davvero flessibile.

Sono convinto che quando ci sono più elementi sull'asse, il modo più logico per justify-selfcomportarsi è allinearsi ai vicini (o ai bordi) più vicini, come dimostrato di seguito.

Spero davvero che il W3C se ne accorga e lo considererà almeno. =)

inserisci qui la descrizione dell'immagine

In questo modo puoi avere un oggetto veramente centrato indipendentemente dalle dimensioni della casella sinistra e destra. Quando una delle scatole raggiunge il punto della casella centrale, la spingerà semplicemente fino a quando non c'è più spazio da distribuire.

inserisci qui la descrizione dell'immagine

La facilità di creare layout fantastici è infinita, dai un'occhiata a questo esempio "complesso".

inserisci qui la descrizione dell'immagine


12
@Mark è fantastico! Grazie per aver dedicato del tempo per redigere questo. Spero non ti dispiaccia ma l'ho presentato qui: discourse.wicg.io/t/flexbox-justify-self-property/1146
Zaqx

1
@Zaqx certo, maggiore è l'esposizione, meglio è. Spero seriamente che troveranno un modo per realizzare questa realtà, mi piacerebbe sporcarmi le mani.
Segna il

1
Ciao Mark, @Zaqx, ho pubblicato una risposta che potrebbe riguardare alcuni dei casi d'uso citati in questa risposta. Ho scoperto che si può ancora fare molto nell'asse principale senza necessità justify-selfe justify-items.
Michael Benjamin,

3
@Michael_B Sono contento che stai imparando di più sulla flexbox e apprezzi che hai impiegato del tempo per formattare le tue note in una risposta. Margine: auto è davvero interessante (anche se troverai i browser che hanno implementato le versioni 2009 e 2012 delle specifiche del flexbox non hanno funzionalità equivalenti che riducono drasticamente la possibilità di usarlo in un sito di produzione). Tuttavia, anche con i browser che supportano il margine: auto, il caso d'uso principale qui di un elemento centrato rispetto al suo contenitore mentre lo spazio esiste è ancora impossibile senza una proprietà legittima o simile.
Zaqx,

1
@Zaqx, grazie per il feedback. E sì, sono d'accordo con te, i automargini non sono un sostituto completo per justify-self. Sono stato attento a esprimere il mio commento precedente dicendo che i automargini copriranno alcuni dei casi d'uso . Come hai notato, non può centrare un oggetto in posizione quando gli oggetti adiacenti hanno dimensioni diverse. Tuttavia, offre più opzioni per l'allineamento di oggetti flessibili. Quando ho iniziato a conoscere Flexbox, ho pensato justify-contentche gli elementi invisibili del distanziatore fossero l'unico modo.
Michael Benjamin,

20

Questo è stato chiesto nell'elenco in stile www e Tab Atkins (editor di specifiche) ha fornito una risposta che spiega il perché . Lo approfondirò un po 'qui.

Per iniziare, supponiamo inizialmente che il nostro contenitore flessibile sia a linea singola ( flex-wrap: nowrap). In questo caso, c'è chiaramente una differenza di allineamento tra l'asse principale e l'asse trasversale - ci sono più oggetti impilati nell'asse principale, ma solo un oggetto impilato nell'asse trasversale. Quindi ha senso avere un "align-self" personalizzabile per elemento nell'asse trasversale (poiché ogni elemento è allineato separatamente, da solo), mentre non ha senso nell'asse principale (poiché lì, il gli articoli sono allineati collettivamente).

Per il flexbox multilinea, la stessa logica si applica a ogni "flex line". In una data linea, gli elementi sono allineati individualmente nell'asse trasversale (poiché esiste un solo elemento per linea, nell'asse trasversale), rispetto collettivamente nell'asse principale.


Ecco un altro modo di formularlo: quindi, tutte le proprietà *-selfe *-contentriguardano come distribuire spazio extra attorno alle cose. Ma la differenza chiave è che le *-selfversioni sono per i casi in cui c'è solo una cosa in quell'asse , e le *-contentversioni sono per quando ci sono potenzialmente molte cose in quell'asse . Gli scenari una cosa contro molte cose sono diversi tipi di problemi e quindi hanno diversi tipi di opzioni disponibili - ad esempio, i valori space-around/ space-betweenhanno senso per *-content, ma non per *-self.

SO: Nell'asse principale di un flexbox, ci sono molte cose su cui distribuire lo spazio. Quindi una *-contentproprietà ha un senso lì, ma non una *-selfproprietà.

Al contrario, nell'asse trasversale, abbiamo sia una *-selfche una *-contentproprietà. Uno determina come distribuiremo lo spazio attorno alle molte linee flessibili ( align-content), mentre l'altro ( align-self) determina come distribuire lo spazio attorno a singoli elementi flessibili nell'asse trasversale, all'interno di una determinata linea flessibile.

(Sto ignorando le *-itemsproprietà qui, dal momento che stabiliscono semplicemente le impostazioni predefinite per *-self.)


1
Capisco come a justify-selfpotrebbe essere un problema su un asse con più articoli invece di un articolo. Tuttavia spero davvero che approfondiranno ulteriormente, in una situazione con più elementi, come si justify-selfcomporterebbe, perché ci sono alcune situazioni in cui ciò potrebbe essere davvero utile. Ad esempio ( stackoverflow.com/questions/32378953/… ).
Segna il

Bello trovare su quella mailing list. Sto cercando di avvolgerci la testa, visto che vedo ancora buone possibilità di utilizzo justify-self.
Michael Benjamin,

Ho aggiunto un po 'più di chiarimenti, spiegando come si *-selftratta dei casi in cui abbiamo solo una cosa da allineare mentre *-contentriguarda i casi in cui abbiamo molte cose da allineare. Questo lo rende un po 'più chiaro?
dholbert,

Sì, è più chiaro. Apprezzo la spiegazione. Ma tutto si riduce a una semplice preferenza degli autori delle specifiche, non a un'esigenza particolare basata sulla logica. Dalla mailing list a cui hai fatto riferimento : Le proprietà * -self funzionano solo se il bambino è tutto solo in quell'asse. Perché? Non sembra esserci bisogno di questo. È una decisione arbitraria. Una preferenza. In effetti, i automargini, anch'essi parte delle specifiche, consentono l'allineamento * -self con più elementi nella riga. Nessun motivo chiaro per cui anche le proprietà delle parole chiave non possono.
Michael Benjamin,

1

So che questo non usa flexbox, ma per il semplice caso d'uso di tre elementi (uno a sinistra, uno al centro, uno a destra), questo può essere realizzato facilmente usando display: gridsul genitore, grid-area: 1/1/1/1;sui bambini e justify-selfper il posizionamento di quei bambini.

<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>


Grazie per la risposta, ma in realtà non risponde alla domanda. Inoltre, c'è un modo più semplice per realizzare il layout: jsfiddle.net/fga89m2o
Michael Benjamin,

0

Ho appena trovato la mia soluzione a questo problema, o almeno il mio problema.
Stavo usando al justify-content: space-aroundposto di justify-content: space-between;.

In questo modo gli elementi finali rimarranno in alto e in basso e, se lo si desidera, si potrebbero avere margini personalizzati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.