Come allineare verticalmente il testo all'interno di una flexbox?


425

Vorrei usare la flexbox per allineare verticalmente alcuni contenuti all'interno di un <li>ma senza avere un grande successo.

Ho controllato online e molti tutorial usano effettivamente un div wrapper che ottiene le align-items:centerimpostazioni flex sul genitore, ma mi chiedo è possibile ritagliare questo elemento aggiuntivo?

Ho scelto di usare flexbox in questa istanza poiché l'altezza dell'elemento dell'elenco sarà dinamica %.

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  align-self: center;
  background: silver;
  width: 100%;
  height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>

Risposte:


545

Invece di usare align-self: centeruse align-items: center.

Non è necessario modificare flex-directiono utilizzare text-align.

Ecco il tuo codice, con una sola modifica, per farlo funzionare:

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  /* align-self: center;    <---- REMOVE */
  align-items: center;   /* <---- NEW    */
  background: silver;
  width: 100%;
  height: 20%; 
}

La align-selfproprietà si applica agli articoli flessibili . Tranne che il tuo linon è un oggetto flessibile perché il suo genitore - il ul- non ha display: flexo display: inline-flexapplicato.

Pertanto, ulnon è un contenitore flessibile, linon è un oggetto flessibile e align-selfnon ha alcun effetto.

La align-itemsproprietà è simile align-self, tranne per i contenitori flessibili .

Poiché liè un contenitore flessibile, align-itemspuò essere utilizzato per centrare verticalmente gli elementi figlio.

demo codepen


Tecnicamente, ecco come align-itemse come align-selffunziona ...

La align-itemsproprietà (sul contenitore) imposta il valore predefinito di align-self(sugli articoli). Pertanto, align-items: centersignifica che tutti gli elementi flessibili saranno impostati su align-self: center.

Ma puoi sovrascrivere questa impostazione predefinita regolando align-selfsu singoli elementi.

Ad esempio, potresti volere colonne di uguale altezza, quindi il contenitore è impostato su align-items: stretch. Tuttavia, un elemento deve essere bloccato in alto, quindi è impostato su align-self: flex-start.

esempio


In che modo il testo è un oggetto flessibile?

Alcune persone potrebbero chiedersi come una sequenza di testo ...

<li>This is the text</li>

è un elemento figlio di li.

Il motivo è che il testo che non è esplicitamente racchiuso da un elemento di livello inline è algoritmicamente racchiuso da un riquadro inline. Questo lo rende un elemento inline anonimo e figlio del genitore.

Dalle specifiche CSS:

9.2.2.1 Caselle incorporate anonime

Qualsiasi testo contenuto direttamente all'interno di un elemento contenitore di blocchi deve essere trattato come un elemento inline anonimo.

Le specifiche del flexbox prevedono comportamenti simili.

4. Articoli flessibili

Ogni figlio in-flow di un contenitore flessibile diventa un oggetto flessibile e ogni sequenza contigua di testo direttamente contenuta all'interno di un contenitore flessibile viene racchiusa in un oggetto flessibile anonimo.

Quindi, il testo in liè un oggetto flessibile.


2
Mi piace align-items: baseline. Buono per diverse altezze provenienti da diversi caratteri Unicode ecc.
qräbnö

1
Grazie per la spiegazione e il collegamento al concetto di caselle incorporate anonime ... aiuta davvero a chiarire perché alcuni effetti che puoi ottenere con prove ed errori funzionano come fanno.
squarecandy,

39

La risposta più votata è per risolvere questo specifico problema pubblicato da OP, in cui il contenuto (testo) veniva racchiuso in un inline-blockelemento. Alcuni casi potrebbero riguardare il centrare un elemento normale verticalmente all'interno di un contenitore , che è stato applicato anche nel mio caso, quindi tutto ciò di cui hai bisogno è:

align-self: center;

25

La mossa migliore è semplicemente annidare un flexbox all'interno di un flexbox . Tutto quello che devi fare è dare al bambino align-items: center. Ciò allinea verticalmente il testo all'interno del suo genitore.

// Assuming a horizontally centered row of items for the parent but it doesn't have to be
.parent {
  align-items: center;
  display: flex;
  justify-content: center;
}

.child {
  display: flex;
  align-items: center;
}

Se vuoi un testo centrato perfetto. text-align:centernon funziona da solo. Usa align-items: centercon esso.
Tzwenni,

8

RISULTATO

inserisci qui la descrizione dell'immagine

HTML

<ul class="list">
  <li>This is the text</li>
  <li>This is another text</li>
  <li>This is another another text</li>
</ul>

Usa align-itemsinvece di align-selfe ho anche aggiunto flex-directiona column.

CSS

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

.list {
  display: flex;
  justify-content: center;
  flex-direction: column;  /* <--- I added this */
  align-items: center;   /* <--- Change here */
  height: 100px;
  width: 100%;
  background: silver;
}

.list li {  
  background: gold;
  height: 20%; 
}

1

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
 display: flex;
 justify-content: center;
 align-items: center;
 background: silver;
 width: 100%;
 height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>


0

* {
  padding: 0;
  margin: 0;
}
html, body {
  height: 100%;
}
ul {
  height: 100%;
}
li {
  display: flex;
  justify-content: center;
  align-items:center;
  background: silver;
  width: 100%;
  height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>


Le risposte di solo codice non sono molto utili ... aggiungi commenti o una spiegazione di ciò che hai fatto e perché funziona.
random_user_name

0

Usando display: flexpuoi controllare l'allineamento verticale degli elementi HTML.

.box {
  height: 100px;
  display: flex;
  align-items: center; /* Vertical */
  justify-content: center; /* Horizontal */
  border:2px solid black;
}

.box div {
  width: 100px;
  height: 20px;
  border:1px solid;
}
<div class="box">
  <div>Hello</div>
  <p>World</p>
</div>


-6

Si potrebbe cambiare il ule lidisplay per tablee table-cell. Quindi, vertical-alignfunzionerebbe per te:

ul {
    height: 20%;
    width: 100%;
    display: table;
}

li {
    display: table-cell;
    text-align: center;
    vertical-align: middle;
    background: silver;
    width: 100%; 
}

http://codepen.io/anon/pen/pckvK


Funziona bene fino a quando non aggiungi un altro elemento dell'elenco.
George,

1
Vero ... Ma questo non è mai stato menzionato
LcSalazar

hai cambiato l'altezza per essere su ul invece di li? ogni altezza sarà dinamica, quindi questo non è qualcosa che potrei usare per paura
styler

@LcSalazar In genere non si utilizza un elenco se si intende avere un solo elemento. Ecco a cosa servono i div.
Ben Visness,

2
Vero di nuovo ... Ma non sto dicendo che questo è lo scenario perfetto. Ho appena pubblicato una soluzione che risponde alla domanda così com'è. Spero che queste informazioni possano tornare utili a qualcun altro che le legge e ha un altro scenario ...
LcSalazar
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.