Di seguito sono cinque opzioni per ottenere questo layout:
- Posizionamento CSS
- Flexbox con elemento DOM invisibile
- Flexbox con pseudo-elemento invisibile
- Flexbox con
flex: 1
- Layout griglia CSS
Metodo n. 1: proprietà di posizionamento CSS
Applicare position: relative
sul contenitore flessibile.
Applica position: absolute
all'articolo D.
Ora questo oggetto è assolutamente posizionato all'interno del contenitore flessibile.
Più specificamente, l'elemento D viene rimosso dal flusso del documento ma rimane entro i limiti dell'antenato posizionato più vicino .
Utilizzare le proprietà di offset CSS top
e right
spostare questo elemento in posizione.
li:last-child {
position: absolute;
top: 0;
right: 0;
background: #ddd;
}
ul {
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p {
text-align: center;
margin-top: 0;
}
span {
background-color: aqua;
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Un avvertimento a questo metodo è che alcuni browser potrebbero non rimuovere completamente un elemento flessibile assolutamente posizionato dal flusso normale. Ciò modifica l'allineamento in modo non standard, inaspettato. Maggiori dettagli: l' elemento flessibile posizionato in modo assoluto non viene rimosso dal flusso normale in IE11
Metodo n. 2: Margini automatici Flex e articolo flessibile invisibile (elemento DOM)
Con una combinazione di auto
margini e un nuovo elemento flessibile invisibile, è possibile ottenere il layout.
Il nuovo oggetto flessibile è identico all'articolo D ed è posizionato all'estremità opposta (il bordo sinistro).
Più specificamente, poiché l'allineamento flessibile si basa sulla distribuzione di spazio libero, il nuovo elemento è un contrappeso necessario per mantenere le tre scatole centrali centrate orizzontalmente. Il nuovo oggetto deve avere la stessa larghezza dell'oggetto D esistente, altrimenti le caselle centrali non saranno centrate con precisione.
Il nuovo elemento viene rimosso dalla vista con visibility: hidden
.
In breve:
- Crea un duplicato
D
dell'elemento.
- Posizionalo all'inizio dell'elenco.
- Uso flex
auto
margini per mantenere A
, B
e C
centrato, con entrambi gli D
elementi creando equilibrio uguale da entrambe le estremità.
- Applica
visibility: hidden
al duplicatoD
li:first-child {
margin-right: auto;
visibility: hidden;
}
li:last-child {
margin-left: auto;
background: #ddd;
}
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
<li>D</li><!-- new; invisible spacer item -->
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Metodo n. 3: Margini automatici Flex e elemento flessibile invisibile (pseudo-elemento)
Questo metodo è simile al n. 2, tranne che è semanticamente più pulito e la larghezza di D
deve essere nota.
- Crea uno pseudo-elemento con la stessa larghezza di
D
.
- Posizionalo all'inizio del contenitore con
::before
.
- Utilizzare flex
auto
margini di mantenere A
, B
e C
perfettamente centrato, con la pseudo e D
elementi creando equilibrio uguale da entrambe le estremità.
ul::before {
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
}
li:last-child {
margin-left: auto;
background: #ddd;
}
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Metodo n. 4: aggiungi flex: 1
agli elementi sinistro e destro
Iniziando con il metodo n. 2 o n. 3 sopra, invece di preoccuparti della stessa larghezza per gli elementi sinistro e destro per mantenere l'equilibrio, basta dare a ciascuno di essi flex: 1
. Ciò li costringerà entrambi a consumare spazio disponibile, centrando così l'elemento centrale.
È quindi possibile aggiungere display: flex
singoli elementi per allinearne il contenuto.
NOTA sull'utilizzo di questo metodo con min-height
: Attualmente in Chrome, Firefox, Edge e possibilmente altri browser, la regola abbreviata siflex: 1
suddivide in questo:
flex-grow: 1
flex-shrink: 1
flex-basis: 0%
Quell'unità percentuale (%) su flex-basis
provoca l'interruzione di questo metodo quando min-height
viene utilizzato sul contenitore. Questo perché, come regola generale, le altezze percentuali sui figli richiedono un'impostazione esplicita della height
proprietà sul genitore.
Questa è una vecchia regola CSS risalente al 1998 ( CSS Level 2 ) che è ancora in vigore in molti browser in un modo o nell'altro. Per i dettagli completi vedere qui e qui .
Ecco un'illustrazione del problema pubblicato nei commenti di user2651804 :
#flex-container {
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
}
#flex-container>div {
background: orange;
margin: 5px;
}
#flex-container>div:first-child {
flex: 1;
}
#flex-container::after {
content: "";
flex: 1;
}
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
La soluzione è non utilizzare l'unità percentuale. Prova px
o semplicemente niente ( che è ciò che le specifiche effettivamente raccomandano , nonostante il fatto che almeno alcuni dei principali browser abbiano aggiunto un'unità percentuale per qualsiasi motivo).
#flex-container {
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
}
#flex-container > div {
background: orange;
margin: 5px;
}
/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */
#flex-container > div:first-child {
flex: 1;
flex-basis: 0;
}
#flex-container::after {
content: "";
flex: 1;
flex-basis: 0;
}
/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY
#flex-container > div:first-child {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
#flex-container::after {
content: "";
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
*/
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
Metodo n. 5: layout griglia CSS
Questo può essere il metodo più pulito ed efficiente. Non è necessario il posizionamento assoluto, elementi falsi o altri hacker.
Basta creare una griglia con più colonne. Quindi posiziona i tuoi articoli nelle colonne centrali e finali. Fondamentalmente, lascia vuota la prima colonna.
ul {
display: grid;
grid-template-columns: 1fr repeat(3, auto) 1fr;
grid-column-gap: 5px;
justify-items: center;
}
li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }
/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p { text-align: center; }
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>| true center |</span></p>