¿Por qué vertical-align: middle no funciona en mi span o div?

246

Estoy tratando de centrar verticalmente un elemento spano divdentro de otro divelemento. Sin embargo cuando lo pongo vertical-align: middle, no pasa nada. He intentado cambiar las displaypropiedades de ambos elementos, y nada parece funcionar.

Esto es lo que estoy haciendo actualmente en mi página web:

.main {
  height: 72px;
  vertical-align: middle;
  border: 1px solid black;
  padding: 2px;
}
    
.inner {
  vertical-align: middle;
  border: 1px solid red;    
}
    
.second {
  border: 1px solid blue; 
}
<div class="main">
  <div class="inner">
    This box should be centered in the larger box
    <div class="second">Another box in here</div>
  </div>
</div>

Aquí hay un jsfiddle de la implementación que muestra que no funciona: http://jsfiddle.net/gZXWC/

Puntilla
fuente

Respuestas:

207

Esta parece ser la mejor manera: ha pasado algún tiempo desde mi publicación original y esto es lo que debería hacerse ahora: http://jsfiddle.net/m3ykdyds/200

/* CSS file */

.main {
    display: table;
}

.inner {
    border: 1px solid #000000;
    display: table-cell;
    vertical-align: middle;
}

/* HTML File */
<div class="main">
    <div class="inner"> This </div>
</div>
Charles Addis
fuente
2
Entonces, ¿cómo hace alguien lo que el OP quiere hacer?
Ryan Mortensen
¿Alguna idea sobre los párrafos de línea variable? es decir. si no hay forma de saber si será una o dos líneas. ¿Necesitaría usar jQuery entonces?
foochow
¿Qué pasa si la altura debe ser dinámica, cuál es la solución?
Murhaf Sousli
no debería ser la respuesta aceptada, se basa en conocer la altura de '.inner', por lo que no es exactamente lo que pedía el OP y algunas respuestas mucho mejores a continuación verán las respuestas de @timbergus o Tim Perkins en la parte inferior.
mike-source
@ mike-source sabiendo que la altura del interior es 100% posible, incluso si la altura es dinámica, ya que un poco de JavaScript puede resolver eso y cambiar dinámicamente la regla CSS para ese objeto DOM.
Charles Addis
143

Usando CSS3:

<div class="outer">
   <div class="inner"/>
</div>

Css:

.outer {
  display : flex;
  align-items : center;
  justify-content: center;
}

Nota: Esto podría no funcionar en viejos IE

usuario1782556
fuente
16
Esto es compatible con los principales navegadores modernos y con la solución más simple y limpia.
Sam
2
También tenga en cuenta inline-flextener varios elementos en una fila dentro del elemento interno.
Dan Nissenbaum
1
En mi caso, dado que también quería centrar el contenido de .inner horizontalmente, tuve que agregar .inner { width: 100%; }. De esta manera, parece funcionar .outer { display: table; } .inner { display: table-cell; vertical-align: middle; }pero sin forzar un ancho mínimo.
Bart S
Solía justify-content: center;alinear horizontalmente, lo que funcionó muy bien
Ruth Young
140

Prueba esto, me funciona muy bien:

/* Internet Explorer 10 */
display:-ms-flexbox;
-ms-flex-pack:center;
-ms-flex-align:center;

/* Firefox */
display:-moz-box;
-moz-box-pack:center;
-moz-box-align:center;

/* Safari, Opera, and Chrome */
display:-webkit-box;
-webkit-box-pack:center;
-webkit-box-align:center;

/* W3C */
display:box;
box-pack:center;
box-align:center;
Mahendra Liya
fuente
44
excelente respuesta, esto me ha dado una solución totalmente funcional que no ha causado otros problemas (una aplicación que usa jquerymobile + phonegap y todas las otras soluciones condujeron a problemas de tamaño css y div). Solo para señalar que estos parámetros deben agregarse a un bloque CSS específico de los elementos a centrar / middled, por ejemplo: #element span {height:100%;display:-webkit-box;-webkit-box-pack:center;-webkit-box-align:center;}- tenga en cuenta que la altura es importante para garantizar que el span herede la altura completa de su contenedor (probablemente un div) de lo contrario ¡todavía no obtendrás centrado vertical!
Andy Lorenz
Por cierto, puede escribir código estándar de flexbox sin prefijos del navegador y luego obtener el prefijo del navegador con el corrector automático github.com/postcss/autoprefixer o mediante la demostración en línea simevidas.jsbin.com/gufoko/quiet
starikovs
2
valor de propiedad no válido boxendisplay
Joaquinglezsantos
Además, la respuesta de @ user1782556 funciona mejor cuando la caja exterior tiene relleno.
iautomation
34

Establecer la altura de la línea a la misma altura que contiene div también funcionará

DEMO http://jsfiddle.net/kevinPHPkevin/gZXWC/7/

.inner {
    line-height:72px;
    border: 1px solid #000000;
}
Kevin Lynch
fuente
1
Publiqué un enlace que explicaba ese método también. Sin embargo, no es mi método preferido, si el resto del diseño no tiene un tamaño fijo, me he encontrado con problemas en ventanas de diferentes tamaños con este método.
Charles Addis
2
Sí, la técnica de altura de línea funciona bien, pero SOLO SI tiene contenido de una sola línea. Se perderán líneas adicionales / se derramarán fuera del contenedor y deberá comenzar de nuevo.
Andy Lorenz
a) line-heighttambién cambiará la altura del elemento interno. b) El elemento interno todavía no está centrado verticalmente con precisión. c) No funciona en elementos que no contienen texto, por ejemplo: <img>o elementos con altura fija.
Alph.Dev
También puede fallar el sistema operativo cruzado (Windows / Mac) debido a las diferencias de representación de fuentes
LocalPCGuy
1
Esto es muy impredecible y a menudo da como resultado una altura adicional en el contenedor.
Desvío
25

En caso de que no pueda confiar en flexbox ... Colóquelo .childen .parentel centro. Funciona cuando los tamaños de píxeles son desconocidos (en otras palabras, siempre) y tampoco hay problemas con IE9 +.

.parent { position: relative; }

.child {
    position: absolute;
    top : 50%;
    left: 50%;
    -ms-transform: translate(-50%, -50%);
    transform    : translate(-50%, -50%);    
}
<div class="parent" style="background:lightyellow; padding:6em"> 
  <div class="child" style="background:gold; padding:1em">&mdash;</div> 
</div>

kornieff
fuente
Esta es en realidad la solución mejor hecha, especialmente porque la mayoría de los proyectos que he visto hasta ahora necesitan compatibilidad con IE9
Jabberwocky
20

Debes ponerte vertical-align: middleel elemento interno, no el elemento externo. Establezca la line-heightpropiedad en el elemento externo para que coincida con la heightdel elemento externo. Luego establecer display: inline-blocky line-height: normalen el elemento interior. Al hacer esto, el texto en el elemento interno se ajustará con una altura de línea normal. Funciona en Chrome, Firefox, Safari e IE 8+

.main {
    height: 72px;
    line-height:72px;
    border: 1px solid black;
}
.inner {
    display: inline-block;
    vertical-align: middle;
    line-height: normal;
}
<div class="main">
    <div class="inner">Vertically centered text</div>
</div>

Violín

Tim Perkins
fuente
Esta es probablemente la forma más simple ... todas las demás respuestas en esta página son innecesariamente torpes / hacky O no son compatibles con navegadores antiguos O dependen de conocer la altura del elemento interno. En realidad no necesita el line-height: normal;y display:inline;funciona también. La ventaja de este método es que no interfiere text-align:center;, con lo que el uso display: table-cell;puede crear problemas. Muy a menudo queremos alinear tanto horizontal como verticalmente. Vea este violín editado: jsfiddle.net/br090prs/36
mike-source
2
@ mike-source la razón para usar line-height: normaly display: inline-blockes para que el texto interno se ajuste correctamente. Si está seguro de que el texto en el div interno nunca se ajustará, entonces estas propiedades no serán necesarias.
Tim Perkins
Desde que Microsoft finalizó el soporte para versiones antiguas de IE , he usado flexbox para este tipo de cosas (como sugirió @ user1782556). Mi respuesta original es el camino a seguir si aún necesita admitir IE 10 o anterior.
Tim Perkins
100% de acuerdo, pero personalmente no elegiría Flex Box todavía, solo el 76% de los navegadores lo admiten completamente a partir de mayo de 2016 (94% si incluye soporte parcial), consulte: caniuse.com/#search=flexible% 20box . Sin embargo, se está acercando mucho a ser la opción más sensata, dependiendo de su base de usuarios.
mike-source
10

Utilicé esto para alinear todo en el centro del contenedor wrap en caso de que ayude a alguien, lo encontré más simple:

div.wrapper {
  /* --- This works --- */
  display: flex;
  /* Align Vertically */
  align-items: center;
  /* Align Horizontally */
  justify-content: center;
  /* --- ---------- ----- */
  width: 100%;
  height:100px;
  background-color: blue;
}
div.inner {
  width: 50px;
  height: 50px;
  background-color: orange;
}
<div class="wrapper">
  <div class="inner">
  </div>
</div>

Ruth Young
fuente
7

Aquí tiene un ejemplo de dos formas de hacer una alineación vertical. Los uso y funcionan bastante bien. Uno usa posicionamiento absoluto y el otro usa flexbox .

Ejemplo de alineación vertical

Con flexbox, puede alinear un elemento por sí mismo dentro de otro elemento con el display: flex;uso align-self. Si necesita alinearlo también horizontalmente, puede usarlo align-itemsy justify-contenten el contenedor.

Si no desea usar flexbox, puede usar la propiedad de posición. Si hace que el contenedor sea relativo y el contenido absoluto, el contenido podrá moverse libremente dentro del contenedor. Entonces, si usa top: 0;y left: 0;en el contenido, se colocará en la esquina superior izquierda del contenedor.

Posicionamiento absoluto

Luego, para alinearlo, solo necesita cambiar las referencias superior e izquierda al 50%. Esto colocará el contenido en el centro del contenedor desde la esquina superior izquierda del contenido.

Alinear en el medio del contenedor

Por lo tanto, debe corregir esto traduciendo el contenido de la mitad de su tamaño a la izquierda y arriba.

Centrado absoluto

Timbergus
fuente
5

Aquí hay un gran artículo sobre cómo alinear verticalmente. Me gusta la forma flotante.

http://www.vanseodesign.com/css/vertical-centering/

El HTML:

<div id="main">
    <div id="floater"></div>
    <div id="inner">Content here</div>
</div>

Y el estilo correspondiente:

#main {
   height: 250px;
}

#floater {
   float: left;
   height: 50%;
   width: 100%;
   margin-bottom: -50px;
}

#inner {
   clear: both;
   height: 100px;
}
Dory Zidon
fuente
3
Creo que si define la altura del bloque #inner invalida el concepto de centrado vertical adecuado. El OPS estaba pidiendo que fuera automático, así que me imagino que eso significa que la altura de la caja interna no se conoce en el momento de la concepción.
Alexis Wilke
5

HTML

<div id="myparent">
  <div id="mychild">Test Content here</div>
</div>

CSS

#myparent {
  display: table;
}
#mychild {
  display: table-cell;
  vertical-align: middle;
}

Configuramos el div padre para que se muestre como una tabla y el div hijo para que se muestre como una celda de tabla. Entonces podemos usar la alineación vertical en el div hijo y establecer su valor en medio. Cualquier cosa dentro de este div hijo estará centrada verticalmente.

Brijesh Patel
fuente
4

Es sencillo. Simplemente agregue display:table-cellen su clase principal.

.main {
  height: 72px;
  vertical-align: middle;
  display:table-cell;
  border: 1px solid #000000;
}

¡Mira este jsfiddle !

RizonBarns
fuente
4

Aquí está la última solución más simple: no es necesario cambiar nada, solo agregue tres líneas de reglas CSS a su contenedor del div en el que desea centrarse. Me encanta Flex Box#LoveFlexBox

.main {
  /* I changed height to 200px to make it easy to see the alignment. */
  height: 200px;
  vertical-align: middle;
  border: 1px solid #000000;
  padding: 2px;
  
  /* Just add the following three rules to the container of which you want to center at. */
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* This is true vertical center, no math needed. */
}
.inner {
  border: 1px solid #000000;
}
.second {
  border: 1px solid #000000;
}
<div class="main">
  <div class="inner">This box should be centered in the larger box
    <div class="second">Another box in here</div>
  </div>
  <div class="inner">This box should be centered in the larger box
    <div class="second">Another box in here</div>
  </div>
</div>

Prima

El justify-contentvalor se puede establecer en las siguientes opciones:

  • flex-start, que alineará el div secundario donde comienza el flujo flexible en su contenedor principal. En este caso, se mantendrá en la cima.

  • center, que alineará el div hijo al centro de su contenedor padre. Esto es realmente bueno, porque no es necesario agregar un div adicional para envolver a todos los niños para colocar el contenedor en un contenedor principal para centrarlos. Por eso, esta es la verdad centro vertical (de column flex-directionmanera similar, si cambia el flow-directiona row, se centrará horizontalmente.

  • flex-end, que alineará el div hijo donde termina el flujo flexible en su contenedor principal. En este caso, se moverá al fondo.

  • space-between, que extenderá a todos los niños desde el principio del flujo hasta el final del flujo. Si la demostración, agregué otro div hijo, para mostrar que están dispersos.

  • space-around, similar a space-between, pero con la mitad del espacio al principio y al final del flujo.

Downhillski
fuente
Solución perfecta. Los navegadores incompatibles pueden desalinear el contenido y el usuario debe manejarlo o actualizar su navegador.
twicejr
0

Dado que vertical-alignfunciona como se espera en un td, puede poner un solo celled tableen el divpara alinear su contenido.

<div>
    <table style="width: 100%; height: 100%;"><tr><td style="vertical-align: middle; text-align: center">
        Aligned content here...
    </td></tr></table>
</div>

Clunky, pero funciona hasta donde puedo decir. Es posible que no tenga los inconvenientes de las otras soluciones.

Smig
fuente
55
No, por favor, ya no hay mesas. CSS puede hacer eso de una manera limpia. No hay necesidad de usar <table> en este caso.
enguerranws ​​03 de
0

Simplemente coloque el contenido dentro de una tabla con una altura del 100% y configure la altura para el div principal

<div style="height:80px;border: 1px solid #000000;">
<table style="height:100%">
<tr><td style="vertical-align: middle;">
  This paragraph should be centered in the larger box
</td></tr>
</table>
</div>
Ramiro Mosquera
fuente
0

Para centrar verticalmente un elemento span o div dentro de otro div, agregue la posición relativa al div padre y la posición absoluta al div hijo. Ahora, el div hijo se puede colocar en cualquier lugar dentro del div. Ejemplo debajo de los centros, tanto horizontal como verticalmente.

<div class="parent">
    <div class="child">Vertically and horizontally centered child div</div>
</div>

css:

.parent{
    position: relative;
}
.child{
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
}
Toki
fuente
0

Este es un enfoque moderno y utiliza la funcionalidad CSS Flexbox. Ahora puede alinear verticalmente el contenido dentro de su contenedor principal simplemente agregando estos estilos al .maincontenedor

.main {
        display: flex;
        flex-direction: column;
        justify-content: center;
}

¡Y estás listo para irte!

Kingsley Gyimah
fuente