Usando margin: auto para alinear verticalmente un div

113

Entonces sé que podemos centrar un div horizontalmente si usamos margin:0 auto;. ¿Debería margin:auto auto;funcionar como creo que debería funcionar? ¿Centrarlo verticalmente también?

¿Por qué tampoco vertical-align:middle;funciona?

.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

salvador
fuente
1
Sugiero encarecidamente leer e implementar la respuesta de @ zpr a continuación con respecto a Flexbox. Está bastante bien soportado a partir de hoy y su CSS será mucho, mucho más limpio.
Govind Rai
if ((nueva Fecha ()). getFullYear ()> 2017) useFlexBox = true;
Brandito

Respuestas:

173

Actualización agosto 2020

Aunque todavía vale la pena leer lo siguiente para obtener información útil, hemos tenido Flexbox desde hace algún tiempo, así que utilícelo, según esta respuesta .


No puedes usar:

vertical-align:middledebido a que es no aplicable a los elementos en bloque

margin-top:autoy margin-bottom:autoporque sus valores usados ​​se calcularían como cero

margin-top:-50%porque los valores de margen basados ​​en porcentajes se calculan en relación con el ancho del bloque contenedor

De hecho, la naturaleza del flujo de documentos y los algoritmos de cálculo de la altura de los elementos hacen que sea imposible utilizar márgenes para centrar un elemento verticalmente dentro de su padre. Siempre que se cambie el valor de un margen vertical, se activará un recálculo de la altura del elemento principal (reflujo), que a su vez desencadenaría un nuevo centro del elemento original ... convirtiéndolo en un bucle infinito.

Puedes usar:

Algunas soluciones alternativas como esta que funcionan para su escenario; los tres elementos tienen que estar anidados así:

.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 funciona bien según Browsershot.

ov
fuente
10
#Es un truco tener la regla con el prefijo solo interpretada por IE7 y menores. Es posible que prefiera en cambio incluir estas reglas en una hoja de estilo IE-específica mediante el uso de los comentarios condicionales , etc.
OV
2
+1 por citar las razones por las que este es el caso, el cálculo del porcentaje de margen basado en el ancho fue muy revelador.
ricosrealm
2
Dudo sobre la declaración de 'bucle infinito'.
Barun
105
la humanidad ya ha estado en la luna hace años y todavía tenemos que lidiar con esta basura. alineación vertical de cosas en un navegador, jesús
user151496
3
En la edad> = IE9, position: absolute; top: 50%; transform: translateY(-50%);también es factible y bastante popular ... (a diferencia de top:50%;margin: - $halfHeightque no tienes que saber la altura de antemano ...)
Frank Nocke
112

Dado que esta pregunta se hizo en 2012 y hemos recorrido un largo camino con la compatibilidad del navegador con flexboxes, sentí que esta respuesta era obligatoria.

Si la pantalla de su contenedor principal es flex, entonces , margin: auto auto(también conocido como margin: auto) funcionará para centrarlo tanto horizontal como verticalmente, independientemente de si es 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>

Tenga en cuenta que no es necesario especificar el ancho / alto de forma absoluta, como en este ejemplo, jfiddle, que usa el tamaño en relación con la ventana gráfica .

Aunque el soporte del navegador para flexboxes está en su punto más alto en el momento de la publicación, muchos navegadores aún no lo admiten o requieren prefijos de proveedor. Consulte http://caniuse.com/flexbox para obtener información actualizada sobre compatibilidad con el navegador.

Actualizar

Dado que esta respuesta recibió un poco de atención, también me gustaría señalar que no necesita especificar marginen absoluto si está usando display: flexy le gustaría centrar todos los elementos en el contenedor:

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

zpr
fuente
4
padre {pantalla: flex; } child {margin: auto 0; } es simplemente genial.
Arek Kostrzeba
Dios mío, eres un hombre estrella de rock, ¡¡¡maldita sea, no puedo votarte más de una vez !!!
PirateApp
Es una buena respuesta cuando también puede confundirse con el problema del contenido adecuado. Al configurar flex en el contenedor, el contenido div no necesita ninguna propiedad para configurar.
Eric
1
Esta es, con mucho, la mejor y elegante solución para trabajar en 2018, gracias.
SilverSurfer
Me gustaría agregar que, a partir de mayo de 2018, con esta solución, el texto no se alinea verticalmente en el medio en IE 11.
Yefu
62

Aquí está la mejor solución que he encontrado: http://jsfiddle.net/yWnZ2/446/ Funciona en Chrome, Firefox, Safari, IE8-11 y Edge.

Si ha declarado un height( height: 1em, height: 50%, etc.) o es un elemento en el que el navegador sabe la altura ( img, svgo canvaspor ejemplo), entonces todo lo que necesita para el centrado vertical es la siguiente:

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

Por lo general, querrá especificar una widtho max-widthpara que el contenido no se extienda a lo largo de toda la pantalla / contenedor.

Si está usando esto para un modal que desea siempre centrado en la ventana gráfica superponiendo otro contenido, use position: fixed;para ambos elementos en lugar de position: absolute. http://jsfiddle.net/yWnZ2/445/

Aquí hay una descripción más completa: http://codepen.io/shshaw/pen/gEiDt

shshaw
fuente
3
Esto no lo centra necesariamente en su elemento padre. Buen truco si solo lo quieres en el centro de la página.
Joel Mellon
2
Simplemente agregue position: relativeal padre y el elemento se centrará dentro del padre. Hice un artículo mucho más extenso en Smashing Magazine sobre la técnica si desea leer más: coding.smashingmagazine.com/2013/08/09/…
shshaw
A veces, el absoluto se basa en uno o dos padres (frente al cuerpo) y el pariente podría ser un abuelo o bisabuelo (frente al padre). Tal vez aquellos que saben cuándo o por qué ocurre eso podrían controlar mejor esta técnica; nunca he investigado realmente esos problemas, pero sé que cambiar de absoluto a relativo no es en sí mismo una solución para que esto funcione. Leí un poco de su artículo y parece que absoluto y relativo van hasta el primer antepasado absoluto o relativo, ¿es correcto?
Joel Mellon
Soy un poco lento. Acabo de volver a leer tu comentario anterior. No me di cuenta de que dijiste que lo agregara al parent... lo tengo. ¡Muchas gracias!
Joel Mellon
1
@commonpike El único problema con IE8 / 9 es si lo usa display: tablepara contenido de altura variable. De lo contrario, este método debería funcionar como se esperaba. Lea el artículo para obtener más detalles en general. También debería poder probar la vista completa en IE8 / 9 para ver si hay algún problema.
shshaw
22

Editar: es 2020, usaría flex box en su lugar.

Respuesta original:

HTML

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

CSS

.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
Gal Margalit
fuente
no funcionaría para IE 8 y versiones anteriores de ie. Dado que se admite la propiedad de transformación (con prefijo -ms-) a partir de la versión 9.0. (es decir, 10 ya no necesitan prefijo).
DevWL
5
Es cierto, no me importa IE8
Gal Margalit
Y el escritor etiquetó html5 para su pregunta ☺
Gal Margalit
9

Sé que la pregunta es de 2012, pero encontré la forma más fácil y quería compartirla.

HTML:

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

y CSS:

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

Si conoce la altura del div que desea centrar , puede colocarlo absolutamente dentro de su padre y luego establecer el topvalor en 50%. Eso colocará la parte superior del div secundario en un 50% del camino hacia abajo de su padre, es decir, demasiado bajo. Vuelva a colocarlo margin-topen la mitad de su altura. Así que ahora tiene el punto medio vertical del div hijo sentado en el punto medio vertical del padre, ¡centrado verticalmente!

Ejemplo:

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

toba
fuente
1
margin-topno se puede establecer en% relativo a la altura del elemento, por lo que terminará con una solución dependiente de las dimensiones
ov
1
¿Cuál es ... exactamente lo que dije en mi respuesta? "Si conoce la altura del div que desea centrar". Y no dije que OP debería usar% in margin-top.
toba el
No estoy de acuerdo con la solución, ya que te bloquea en una altura de elemento predefinida, pero tu comentario tiene sentido. Es posible que desee reflejar eso en la respuesta
ov
3
OK, he puesto en negrita la parte que pasaste por alto, espero que ahora esté más clara.
toba el
1
@ov: si el elemento no tiene una altura fija, puede usar JS para obtener la altura calculada y luego establecer el margen superior negativo en consecuencia. Este sigue siendo el mejor método para centrar verticalmente, en mi opinión.
daGUY
3

Esas dos soluciones requieren solo dos elementos anidados.
Primero - Posicionamiento relativo y absoluto si el contenido es estático (centro manual).

.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 para un diseño fluido : para el centro de contenido exacto, utilice el siguiente ejemplo:

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

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

Necesita establecer una 'altura mínima' en caso de que el contenido supere el 50% de la altura de la ventana. También puede manipular esta altura con la consulta de medios para dispositivos móviles y tabletas. Pero solo si juegas con un diseño receptivo.

Supongo que podría ir más allá y usar un script simple de JavaScript / JQuery para manipular la altura mínima o la altura fija si es necesario por alguna razón.

En segundo lugar , si el contenido es fluido , también puede usar las propiedades CSS de tabla y celda de tabla con alineación vertical y alineación de texto centrada:

/*in a wrapper*/  
display:table;   

y

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

Funciona y escala a la perfección, a menudo se utiliza como solución de diseño web receptivo con diseños de cuadrícula y consulta de medios que manipulan el ancho del objeto.

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

Prefiero la solución de tabla para el centrado exacto del contenido, pero en algunos casos el posicionamiento absoluto relativo funcionará mejor, especialmente si no queremos mantener la proporción exacta de alineación del contenido.

DevWL
fuente
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>

Seetpal singh
fuente
¿Podría compartir con nosotros de qué se trata esta solución? Además, veo su "mensaje emergente" en la parte inferior sin centrar
Alex
Me perdí algo, pero ahora está refinado para mantener el div en el medio verticalmente. puedes comprobarlo ahora.
Seetpal singh
0

No hay una manera fácil de centrar div verticalmente que funcione en todas las situaciones.

Sin embargo, hay muchas formas de hacerlo según la situación.

Éstos son algunos de ellos:

  • Establecer el relleno superior e inferior del elemento principal, por ejemplo, relleno: 20px 0px 20px 0px
  • Use table, la celda de la tabla centra su contenido verticalmente
  • Establezca la posición relativa del elemento principal y los div que desea centrar verticalmente en absoluto y ajústelo como top: 50px; abajo: 50px; por ejemplo

También puede buscar en Google "centrado vertical CSS"

hasu
fuente
0

altura variable, margen superior e inferior automático

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

altura variable, margen superior e inferior automático

usuario3668456
fuente
0

Usando 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 */
}

Ver resultado

DanielBlazquez
fuente
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>
Sudipto Chakraborty
fuente