Domanda Perché "margin: auto" non centra verticalmente un elemento?


Come puoi vedere nella demo qui sotto, margin: auto; centra il blu div orizzontalmente, ma non verticalmente. Perchè no?

.box {
  border: 1px solid red;
  width: 100px;
  height: 100px;
}
.center {
  background: blue;
  width: 50px;
  height: 50px;
  margin: auto;
}
<div class="box">
  <div class="center"></div>
</div>

La mia domanda non è chiedere soluzioni alternative.


44
2017-12-31 22:30


origine


risposte:


Come accennato, questo comportamento è specificato in sezione 10.6.2 di CSS2.1, ed è rimasto invariato da CSS2.

Le scatole di blocchi sono impilate verticalmente dall'alto verso il basso nel flusso normale. Inoltre, i margini verticali possono collassare, e lo fanno solo in determinate circostanze (nella tua demo, il bordo sull'elemento genitore impedirà che eventuali margini sull'elemento figlio possano crollare con il proprio). Se si dispone solo di una tale casella di blocco e l'altezza del blocco contenitore è automatica, i suoi margini superiore e inferiore saranno ugualmente zero. Ma se hai più di una scatola di blocchi nello stesso flusso, o anche scatole fuori flusso che influenzano il layout delle scatole di flusso (nel caso di autorizzazione per esempio), come ti aspetteresti che i margini automatici si risolvano per quelle scatole di flusso?

Questo è il motivo per cui i margini sinistro e destro automatici sono ugualmente azzerati per gli elementi in linea (inclusa la linea atomica) e i galleggianti (anche se i margini orizzontali non collassano mai). Le caselle a livello interno sono posato lungo scatole di lineae anche i carri obbediscono regole di layout uniche.

Le scatole posizionate in modo assoluto sono una storia diversa: poiché non sono mai a conoscenza di altre caselle nello stesso contesto di posizionamento di se stesse, margini superiori e inferiori automatici può essere calcolato per loro in relazione ai blocchi che contengono senza doversi preoccupare di altre scatole che interferiscono mai.

Flexbox è anche una storia diversa: ciò che distingue il layout flessibile dal layout a blocchi è che gli articoli flessibili sono per definizione sempre a conoscenza di altri articoli flessibili nello stesso contesto di formattazione flessibile, incluso il fatto che non ce ne sono. In particolare, nessuno dei due può fluttuare nel contenitore flessibile, né puoi fluttuare gli elementi flessibili per sovvertire questo (anche se è ancora possibile rimuovere un elemento figlio dal layout flessibile completamente con posizionamento assoluto). I margini si comportano in modo molto diverso con gli elementi flessibili dovuti in parte a questo. Vedi sezioni 4.2, 9.5 e 9.6.


33
2017-12-31 22:58



Perché ... perché il Spec. W3C lo dice

Se 'margin-top' o 'margin-bottom' sono 'auto', il loro valore usato è 0.

Per quanto riguarda il vero "perché" ... la query dovrebbe essere davvero affrontata lì.


30
2017-12-31 22:41



Non centra l'elemento verticalmente perché è un elemento a livello di blocco nel flusso normale. Quindi, il si applica la seguente regola:

Se margin-top, o margin-bottom siamo auto, il loro valore usato è 0.

Vale anche la pena ricordare che la regola sopra vale anche per i seguenti elementi: (vedi punti 10.6.2 e 10.6.3 per maggiori informazioni e condizioni).

  • Elementi sostituiti in linea
  • Elementi sostituiti a livello di blocco nel flusso normale
  • inline-block elementi sostituiti nel flusso normale
  • Elementi sostituiti mobili
  • Elementi non sostituiti a livello di blocco in flusso normale quando overflow calcola a visible

Con ciò detto, assolutamente posizionato, elementi non sostituiti che non hanno top, height, e bottom valori di auto sono un'eccezione a questa regola. Quanto segue si applica da punto 10.6.4:

Se nessuno dei tre top, height, e bottom siamo auto e se entrambi margin-top e margin-bottom siamo auto, risolvere l'equazione sotto il vincolo extra che i due margini ottengono valori uguali.

Vedere l'esempio di seguito che mostra come un elemento posizionato in modo assoluto è centrato verticalmente usando margin: auto. Funziona perché nessuna delle tre proprietà top, height, e bottom avere un valore di auto:

.box {
  border: 1px solid red;
  width: 100px;
  height: 100px;
  position: relative;
}
.center {
  background: blue;
  width: 50px;
  height: 50px;
  margin: auto;
  position: absolute;
  top: 0; right: 0;
  bottom: 0; left: 0;
}
<div class="box">
  <div class="center"></div>
</div>

Inoltre, probabilmente vale la pena segnalarlo seguendo la regola anche:

Se uno di margin-top o margin-bottom è auto, risolvi l'equazione per quel valore. Se i valori sono eccessivamente vincolati, ignorare il valore per bottom e risolvere per quel valore.

Ciò significa che se l'elemento posizionato in modo assoluto ha a margin-top valore di auto e a margin-bottom valore di 0 (Cioè, margin: auto auto 0), l'elemento sarebbe assolutamente posizionato in basso rispetto al genitore come nell'esempio seguente:

.box {
  border: 1px solid red;
  width: 100px;
  height: 100px;
  position: relative;
}
.center {
  background: blue;
  width: 50px;
  height: 50px;
  margin: auto auto 0;
  position: absolute;
  top: 0; right: 0;
  bottom: 0; left: 0;
}
<div class="box">
  <div class="center"></div>
</div>


16
2017-12-31 23:02



Perché no margin:auto lavoro in verticale?

In realtà, lo fa - non solo per tutti display valore.

Se display è flex, margin: auto centri sia verticalmente che orizzontalmente.

Lo stesso vale per display: inline-flex, display: grid e display: inline-grid.

.box {
  border: 1px solid red;
  width: 100px;
  height: 100px;
  display: flex; /* new */
}
.center {
  background: blue;
  width: 50px;
  height: 50px;
  margin: auto;
}
<div class="box">
  <div class="center"></div>
</div>


13
2017-12-31 23:36



È a causa dell'effettiva possibilità di conoscere la vera altezza dell'elemento in cui vuoi centrare verticalmente. Per capirlo, pensa prima a come funziona il centraggio orizzontale automatico. Hai un div a cui hai dato una larghezza (fissa o percentuale). La larghezza può essere calcolata in una certa misura. Se è a larghezza fissa, ottimo. Se è flessibile o reattivo (percentuale), almeno hai un intervallo che la larghezza coprirà prima di raggiungere il punto di interruzione successivo. Prendi quella larghezza, meno qualsiasi cosa sia dentro e dividi il resto su entrambi i lati.

Ora, con queste informazioni, come potrebbe il browser calcolare la quantità infinita di variazioni in cui il tuo div crescerà verticalmente? Tieni a mente la dimensione dell'elemento, l'involucro di testo, i paddings e la reattività modificheranno anche la larghezza e imporranno il testo a un ulteriore avvolgimento, e via, e su di esso andrà.

È un compito impossibile? Non è vero, i CSS hanno dedicato tempo e impegno a coprirlo? Non vale il loro tempo, immagino.

E questa è fondamentalmente la risposta che dico ai miei studenti.

Ma ... non preoccuparti! Bootstrap v4 alpha ha capito centraggio verticale!

MODIFICARE

Mi spiace di doverlo modificare in ritardo, ma ho pensato che potreste voler considerare queste soluzioni per centrare verticalmente ed è piuttosto semplice facendo uso della funzione calc

<div class="foo"></div>

.foo {
  background-color: red;
  height: 6em;
  left: calc(50% - 3em);
  position: absolute;
  top: calc(50% - 3em);
  width: 6em;
}

Guardalo QUI


3
2017-12-31 23:05