2015-12-31 20 views
42

Come si può vedere nella demo di seguito, margin: auto; centra il blu div orizzontalmente, ma non verticalmente. Perchè no?Perché "margin: auto" non centra verticalmente un elemento?

.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 sta chiedendo soluzioni alternative.

+0

Semplicemente non lo fa. Il caso d'uso per centrare il contenuto orizzontalmente era presumibilmente molto più comune di farlo verticalmente. – TZHX

+0

@TZHX Tecnicamente, * può * centrare verticalmente. Vedi questo esempio - https://jsfiddle.net/skdjhpo8/ –

+0

L'allineamento verticale in CSS è un mito –

risposta

32

Come accennato, questo comportamento è specificato in section 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, vertical margins may collapse, e lo fai solo in determinate circostanze (nella tua demo, il bordo sull'elemento padre impedirà che eventuali margini sull'elemento figlio vengano compressi 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 clearance per esempio), come ti aspetteresti che i margini automatici si risolvano per quelli scatole di flusso?

Questo è il motivo per cui i margini sinistro e destro automatici vengono 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 laid along line boxes e anche i float obbediscono a unique layout rules.

Le caselle posizionate in modo assoluto sono una storia diversa: poiché non sono mai a conoscenza di altre caselle nello stesso contesto di posizionamento di loro stesse, auto top and bottom margins can be calculated for them with respect to their containing blocks senza doversi preoccupare di eventuali altre caselle che interferiscono.

Flexbox è anche una storia diversa: ciò che definisce il layout flessibile a parte il layout blocco è che gli elementi flessibili sono per definizione sempre a conoscenza di altri elementi di flessione nello stesso contesto di formattazione flex, compreso il fatto che non ce ne sono. In particolare, neither can floats intrude into the flex container, nor can you float flex items to subvert this (sebbene sia ancora possibile rimuovere un elemento figlio dal layout flessibile completamente con absolute positioning). I margini si comportano in modo molto diverso con gli elementi flessibili dovuti in parte a questo. Vedere le sezioni 4.2, 9.5 e 9.6.

27

Perché ... perché lo dice W3C spec.

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

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

16

Non centra l'elemento verticalmente perché è un elemento a livello di blocco nel flusso normale. Così, il following rule applies:

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

E 'anche la pena sottolineare che la regola di cui sopra vale anche per i seguenti elementi così: (vedere i punti 10.6.2 e 10.6.3 per ulteriori informazioni e condizioni).

  • linea sostituiti elementi
  • elementi di blocco sostituito nel flusso normale
  • inline-block elementi rimpiazzati nel flusso normale
  • flottanti elementi sostituiti
  • elementi
  • a livello di blocco non-rimpiazzati nel flusso normale quando overflow calcola a visible

Con ciò detto, elementi posizionati in modo assoluto, non sostituiti che non hanno top, height e bottom valori di auto sono un'eccezione a questa regola. Si applica quanto segue da point 10.6.4:

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

vedere l'esempio seguente dimostra come un elemento posizionato in modo assoluto sia inserito verticalmente utilizzando margin: auto. Funziona perché nessuna delle tre proprietà top, height, e bottom hanno 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 la pena sottolineare la following rule così:

Se uno di margin-top o margin-bottom è auto, risolvere 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 posizionamento assoluto ha un valore margin-top di auto e un valore margin-bottom di 0 (cioè margin: auto auto 0), l'elemento sarebbe assolutamente posizionato relativa inferiore al genitore come nell'esempio qui sotto :

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

3

E 'a causa della effettiva possibilità di conoscere la vera altezza del elem ent 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 quelle informazioni, come potrebbe il browser calcolare l'infinita quantità di variazioni in cui il div si svilupperà 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 preoccupatevi! Bootstrap v4 alpha ha capito vertical centering!

EDIT

Siamo spiacenti di modificare questo ritardo, ma ho pensato che si può prendere in considerazione questa soluzione per centrare verticalmente ed è abbastanza semplice, facendo uso della funzione di calc

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

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

Guardalo HERE

+5

Sarebbe più vero dire che ** Flexbox ** ha immaginato il nostro centraggio verticale e B4a è saltato sul carro. –

+0

Questo, non ne ero a conoscenza – LOTUSMS

12

Un sacco di ottime risposte pubblicate qui. Verrò a questo da una diversa angolazione.

Perché lo margin:auto non funziona in verticale?

In realtà, lo fa – non solo per ogni valore display.

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>