Utilizzando margin: auto per allineare verticalmente un div


113

Quindi so che possiamo centrare un div orizzontalmente se usiamo margin:0 auto;. Dovrebbe margin:auto auto;funzionare come penso che dovrebbe funzionare? Centrandolo anche verticalmente?

Perché non vertical-align:middle;funziona neanche?

.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    background:yellow;
    width:200px;
    margin:auto auto;
    padding:10px;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>

JSFiddle


1
Consiglio vivamente di leggere e implementare la risposta di @ zpr di seguito relativa a Flexbox. È abbastanza ben supportato da oggi e il tuo CSS sarà molto, molto più pulito.
Govind Rai

if ((new Date ()). getFullYear ()> 2017) useFlexBox = true;
Brandito

Risposte:


173

Aggiornamento agosto 2020

Anche se vale ancora la pena leggere quanto segue per le informazioni utili, abbiamo Flexbox da un po 'di tempo, quindi usalo, come da questa risposta .


Non puoi usare:

vertical-align:middleperché è non applicabile a elementi di blocco

margin-top:autoe margin-bottom:autoperché i valori utilizzati sarebbero calcolati come zero

margin-top:-50%perché i valori dei margini basati sulla percentuale sono calcolati rispetto alla larghezza del blocco contenitore

In effetti, la natura del flusso di documenti e gli algoritmi di calcolo dell'altezza dell'elemento rendono impossibile utilizzare i margini per centrare un elemento verticalmente all'interno del suo genitore. Ogni volta che il valore di un margine verticale viene modificato, attiverà un ricalcolo dell'altezza dell'elemento genitore (riflusso), che a sua volta innescherebbe un ricentramento dell'elemento originale ... rendendolo un ciclo infinito.

Puoi usare:

Alcune soluzioni alternative come questa che funzionano per il tuo scenario; i tre elementi devono essere annidati in questo modo:

.container {
    display: table;
    height: 100%;
    position: absolute;
    overflow: hidden;
    width: 100%;
}
.helper {
    #position: absolute;
    #top: 50%;
    display: table-cell;
    vertical-align: middle;
}
.content {
    #position: relative;
    #top: -50%;
    margin: 0 auto;
    width: 200px;
    border: 1px solid orange;
}
<div class="container">
    <div class="helper">
        <div class="content">
            <p>stuff</p>
        </div>
    </div>
</div

JSFiddle funziona bene secondo Browsershot.


10
#è un trucco per avere il prefisso della regola interpretato solo da IE7 e sotto. Potresti preferire invece includere queste regole in un foglio di stile specifico di IE utilizzando commenti condizionali ecc.
ov

2
+1 per la citazione dei motivi per cui questo è il caso, il calcolo della percentuale del margine basato sulla larghezza è stato molto illuminante.
ricosrealm

2
Dubito dell'affermazione "ciclo infinito".
Barun

105
l'umanità è già stata sulla luna anni fa e dobbiamo ancora affrontare questa stronzata. allineare verticalmente le cose in un browser, jesus
user151496

3
Nell'era> = IE9, position: absolute; top: 50%; transform: translateY(-50%);è anche fattibile e abbastanza popolare ... (a differenza top:50%;margin: - $halfHeightdi non è necessario conoscere l'altezza in anticipo ...)
Frank Nocke

112

Poiché questa domanda è stata posta nel 2012 e abbiamo fatto molta strada con il supporto del browser per le flexbox, ho sentito che questa risposta fosse obbligatoria.

Se la visualizzazione del contenitore principale è flex, allora , margin: auto auto(noto anche come margin: auto) funzionerà per centrarlo sia orizzontalmente che verticalmente, indipendentemente dal fatto che si tratti di un elemento inlineo block.

#parent {
    width: 50vw;
    height: 50vh;
    background-color: gray;
    display: flex;
}
#child {
    margin: auto auto;
}
<div id="parent">
    <div id="child">hello world</div>
</div>

Notare che la larghezza / altezza non devono essere specificate in modo assoluto, come in questo esempio jfiddle che utilizza il dimensionamento relativo al viewport.

Sebbene il supporto del browser per le flexbox sia ai massimi storici al momento della pubblicazione, molti browser non lo supportano ancora o richiedono i prefissi del fornitore. Fare riferimento a http://caniuse.com/flexbox per informazioni aggiornate sul supporto del browser.

Aggiornare

Poiché questa risposta ha ricevuto un po 'di attenzione, vorrei anche sottolineare che non è necessario specificare marginaffatto se stai utilizzando display: flexe vorresti centrare tutti gli elementi nel contenitore:

#parent {
    width: 50vw;
    height: 50vh;
    background-color: gray;
    display: flex;
    align-items: center; /* horizontal */
    justify-content: center; /* vertical */
}
<div id="parent">
    <div>hello world</div>
</div>


4
genitore {display: flex; } figlio {margin: auto 0; } è semplicemente fantastico.
Arek Kostrzeba

OMG amico, sei un uomo rockstar, accidenti non posso votarti più di una volta !!!
PirateApp

È una buona risposta quando potresti anche essere confuso con il problema del contenuto di adattamento. Impostando flex sul contenitore, il div del contenuto non necessita di alcuna proprietà da impostare.
Eric,

1
Questa è di gran lunga la soluzione migliore ed elegante per lavorare nel 2018, grazie.
SilverSurfer

Vorrei aggiungere che, a partire da maggio 2018, con questa soluzione, il testo non allinea verticalmente al centro in IE 11.
Yefu

62

Ecco la migliore soluzione che ho trovato: http://jsfiddle.net/yWnZ2/446/ Funziona con Chrome, Firefox, Safari, IE8-11 e Edge.

Se avete un dichiarato height( height: 1em, height: 50%, etc.) o è un elemento in cui il browser conosce l'altezza ( img, svg, o canvasper esempio), allora tutto ciò che serve per la centratura verticale è questo:

.message {
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
    margin: auto;
}

È solitamente desidera specificare un widtho max-widthmodo che il contenuto non si allunga per tutta la lunghezza dello schermo / contenitore.

Se stai usando questo per un modale che vuoi sempre centrato nella finestra che si sovrappone ad altri contenuti, usa position: fixed;per entrambi gli elementi invece di position: absolute. http://jsfiddle.net/yWnZ2/445/

Ecco un articolo più completo: http://codepen.io/shshaw/pen/gEiDt


3
Questo non lo centra necessariamente nel suo elemento genitore. Bel trucco se lo vuoi solo al centro della pagina però.
Joel Mellon

2
Basta aggiungere position: relativeal genitore e l'elemento sarà centrato all'interno del genitore. Ho scritto un articolo molto più ampio su Smashing Magazine sulla tecnica se desideri leggere di più: coding.smashingmagazine.com/2013/08/09/…
shshaw

A volte l'assoluto si basa su uno o due genitori (contro il corpo) e un parente potrebbe essere un nonno o un bisnonno (contro il genitore). Forse coloro che sanno quando o perché ciò accade potrebbero controllare meglio questa tecnica - Non ho mai veramente esaminato questi problemi, ma so che passare dall'assoluto al relativo non è di per sé una soluzione per far funzionare questo. Ho letto un po 'del tuo articolo e sembra che l'assoluto e il relativo risalgano al primo antenato assoluto o relativo, è corretto?
Joel Mellon

Sono un po 'lento. Ho appena riletto il tuo commento sopra. Non ho notato che hai detto di aggiungerlo a parent- capito. Grazie mille!
Joel Mellon

1
@commonpike L'unico problema con IE8 / 9 è se si utilizza display: tableper contenuti ad altezza variabile. In caso contrario, questo metodo dovrebbe funzionare come previsto. Leggi il commento per maggiori dettagli in generale. Dovresti anche essere in grado di testare la visualizzazione completa in IE8 / 9 per vedere se ci sono problemi.
shshaw

22

Modifica: è il 2020, invece userei il flex box.

Risposta originale:

html

<body>
  <div class="centered">
  </div>
</body>

CSS

.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

non funzionerebbe per IE 8 e versioni precedenti di ie. Poiché la proprietà di trasformazione è supportata (con il prefisso -ms-) dalla versione 9.0 in poi. (es. 10 non hanno più bisogno del prefisso).
DevWL

5
È vero, non mi interessa IE8
Gal Margalit

E lo scrittore ha taggato html5 per la sua domanda ☺
Gal Margalit

9

So che la domanda è del 2012, ma ho trovato il modo più semplice in assoluto e volevo condividere.

HTML:

<div id="parent">
     <div id="child">Content here</div>
</div>

e CSS:

#parent{
     height: 100%;
     display: table;
}    
#child {
     display: table-cell;
     vertical-align: middle; 
}

7

Se conosci l'altezza del div che vuoi centrare , puoi posizionarlo assolutamente all'interno del suo genitore e quindi impostare il topvalore su 50%. Ciò metterà la parte superiore del div figlio del 50% verso il basso rispetto al genitore, cioè troppo in basso. Tiralo indietro impostandolo margin-topa metà della sua altezza. Quindi ora hai il punto medio verticale del div bambino seduto nel punto medio verticale del genitore - centrato verticalmente!

Esempio:

.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    background:yellow;
    width:200px;
    margin:auto auto;
    padding:10px;
    position: absolute;
    top: 50%;
    margin-top: -25px;
    height: 50px;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>

http://jsfiddle.net/yWnZ2/2/


1
margin-topnon può essere impostato in% rispetto all'altezza dell'elemento, quindi ti ritroverai con una correzione dipendente dalle dimensioni
ov

1
Che è ... esattamente quello che ho detto nella mia risposta? "Se conosci l'altezza del div che vuoi centrare". E non ho detto che OP dovrebbe usare% in margin-top.
tufo

Non sono d'accordo con la soluzione in quanto ti blocca in un'altezza di elemento predefinita, ma il tuo commento ha senso. Potresti riflettere questo nella risposta
ov

3
OK, ho messo in grassetto la parte che hai trascurato, spero che sia più chiaro ora.
tufo

1
@ov: se l'elemento non ha un'altezza fissa, puoi semplicemente usare JS per ottenere l'altezza calcolata e quindi impostare il margine superiore negativo di conseguenza. Questo è ancora il metodo migliore per centrare verticalmente, secondo me.
daGUY

3

Queste due soluzioni richiedono solo due elementi annidati.
Primo : posizionamento relativo e assoluto se il contenuto è statico (centro manuale).

.black {
    position:relative;
    min-height:500px;
    background:rgba(0,0,0,.5);

}
.message {
    position:absolute;
    margin: 0 auto;
    width: 180px;
    top: 45%; bottom:45%;  left: 0%; right: 0%;
}

https://jsfiddle.net/GlupiJas/5mv3j171/

o per il design fluido - per l'esatto centro dei contenuti usa invece l'esempio seguente:

.message {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

https://jsfiddle.net/GlupiJas/w3jnjuv0/

È necessario impostare "altezza minima" nel caso in cui il contenuto superi il 50% dell'altezza della finestra. Puoi anche modificare questa altezza con media query per dispositivi mobili e tablet. Ma solo se giochi con il responsive design.

Immagino che potresti andare oltre e utilizzare un semplice script JavaScript / JQuery per manipolare l'altezza minima o l'altezza fissa se ce n'è bisogno per qualche motivo.

Secondo : se il contenuto è fluido, puoi anche utilizzare le proprietà CSS di tabella e cella di tabella con allineamento verticale e allineamento del testo centrato:

/*in a wrapper*/  
display:table;   

e

/*in the element inside the wrapper*/
display:table-cell;
vertical-align: middle;
text-align: center;

Funziona e scala perfettamente, spesso utilizzato come soluzione di web design reattivo con layout a griglia e media query che manipolano la larghezza dell'oggetto.

.black {
    display:table;
    height:500px;
    width:100%;
    background:rgba(0,0,0,.5);

}
.message {
    display:table-cell;
    vertical-align: middle;
    text-align: center;
}

https://jsfiddle.net/GlupiJas/4daf2v36/

Preferisco la soluzione tabella per il centraggio esatto del contenuto, ma in alcuni casi il posizionamento assoluto relativo farà un lavoro migliore, soprattutto se non vogliamo mantenere la proporzione esatta dell'allineamento del contenuto.


2

.black {
    display:flex;
    flex-direction: column;
    height: 200px;
    background:grey
}
.message {
    background:yellow;
    width:200px;
    padding:10px;
    margin: auto auto;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>


Potresti condividere con noi come si tratta di questa soluzione? Inoltre, vedo il tuo "messaggio popup" in basso non centrato
Alex

Mi sono perso qualcosa, ma ora è stato perfezionato per mantenere il div al centro in verticale. puoi controllare ora.
Seetpal singh

0

Non esiste un modo semplice per centrare div verticalmente che farebbe il trucco in ogni situazione.

Tuttavia, ci sono molti modi per farlo a seconda della situazione.

Eccone alcuni:

  • Imposta il padding superiore e inferiore dell'elemento genitore, ad esempio padding: 20px 0px 20px 0px
  • Usa tabella, la cella della tabella centra il suo contenuto verticalmente
  • Imposta la posizione relativa dell'elemento genitore e il div che vuoi centrare verticalmente su assoluto e definiscilo come top: 50px; bottom: 50px; per esempio

Puoi anche cercare su Google "centratura verticale CSS"


0

altezza variabile, margine superiore e inferiore automatico

.black {background:rgba(0,0,0,.5);
width: 300px;
height: 100px;
display: -webkit-flex; /* Safari */
display: flex;}
.message{
background:tomato;
margin:auto;
padding:5%;
width:auto;
}
<div class="black">
<div class="message">
    This is a popup message.
</div>

altezza variabile, margine superiore e inferiore automatico


0

Utilizzando Flexbox:

HTML:

<div class="container">
  <img src="http://lorempixel.com/400/200" />
</div>

CSS:

.container {
  height: 500px;
  display: flex;
  justify-content: center; /* horizontal center */
  align-items: center;     /* vertical center */
}

Visualizza il risultato


0
.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    position: absolute;
    top:50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background:yellow;
    width:200px;
    padding:10px;
}

 - 


----------


<div class="black">
<div class="message">
    This is a popup message.
</div>
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.