¿Cómo centrar verticalmente el contenido con altura variable dentro de un div?

158

¿Cuál es la mejor manera de centrar verticalmente el contenido de un div cuando la altura del contenido es variable? En mi caso particular, la altura del contenedor div es fija, pero sería genial si hubiera una solución que funcione en los casos en que el contenedor también tenga una altura variable. Además, me encantaría una solución sin o con muy poco uso de hacks CSS y / o marcado no semántico.

texto alternativo

jessegavin
fuente
el método en ese artículo se desmorona en Safari (4.0.5): S
77
@ ripper234 No exactamente, ya que esta pregunta es sobre la altura variable div
Rauli Rajande
9
Además, esta pregunta se hizo primero.
Gui Imamura

Respuestas:

147

Solo agrega

position: relative;
top: 50%;
transform: translateY(-50%);

a la div interior.

Lo que hace es mover el borde superior del div interno a la mitad de la altura del div externo ( top: 50%;) y luego el div interno hacia arriba a la mitad de su altura ( transform: translateY(-50%)). Esto funcionará con position: absoluteo relative.

Tenga en cuenta eso transformy translatetenga prefijos de proveedor que no están incluidos por simplicidad.

Codepen: http://codepen.io/anon/pen/ZYprdb

BlackCetha
fuente
66
Me preguntaba por qué esto funciona en Chrome y Firefox, pero no en Safari. Luego noté que la mayoría de transformlas cosas relacionadas tienen el -webkit-prefijo y ahora funciona. Así que solo como recordatorio: no olvides agregar el -webkit-prefijo también.
miho
55
Use una herramienta como github.com/postcss/autoprefixer para manejar los prefijos por usted.
Jamie Chong
66
Esta respuesta debe estar en la parte superior.
Jose Faeti
3
¡Esto debería tener muchos más votos a favor! Por cierto, también funciona con position: absolute, ¿no?
caw
44
Este método tiene un efecto secundario desafortunado en Chrome: si su contenedor tiene un número impar de píxeles translate, todo se volverá borroso al intentar manejar .5px de altura en todo.
Keith
157

Esta parece ser la mejor solución que he encontrado para este problema, siempre que su navegador admita el ::beforepseudo elemento: CSS-Tricks: Centrarse en lo desconocido .

No requiere ningún marcado adicional y parece funcionar extremadamente bien. No pude usar el display: tablemétodo porque los tableelementos no obedecen a la max-heightpropiedad.

.block {
  height: 300px;
  text-align: center;
  background: #c0c0c0;
  border: #a0a0a0 solid 1px;
  margin: 20px;
}

.block::before {
  content: '';
  display: inline-block;
  height: 100%; 
  vertical-align: middle;
  margin-right: -0.25em; /* Adjusts for spacing */

  /* For visualization 
  background: #808080; width: 5px;
  */
}

.centered {
  display: inline-block;
  vertical-align: middle;
  width: 300px;
  padding: 10px 15px;
  border: #a0a0a0 solid 1px;
  background: #f5f5f5;
}
<div class="block">
    <div class="centered">
        <h1>Some text</h1>
        <p>But he stole up to us again, and suddenly clapping his hand on my
           shoulder, said&mdash;"Did ye see anything looking like men going
           towards that ship a while ago?"</p>
    </div>
</div>

Fadi
fuente
3
Ahora, eso es una solución BRILLANTE. Muchas gracias por publicar esto!
Troy Alford
Al igual que con la otra respuesta, esta sería mucho mejor si describiera el enfoque e incluyera el código del enlace.
KatieK
3
+1, ¡esta solución es realmente bastante ingeniosa! Por cierto, podría agregar .block { white-space: nowrap; font-size: 0; line-height: 0; }y dejar el margen derecho negativo en el pseudo elemento, solo tiene que restablecer fs y lh en .centrado ... de esta manera se asegura de que el elemento se colocará correctamente incluso si es más ancho que la ventana gráfica (y no No tengo que usar el IMO un margen negativo un poco desordenado).
Simon
@jessegavin: en su opinión ... ¿cómo se compara lo siguiente con el enfoque que ha descrito: stackoverflow.com/questions/396145/…
pulkitsinghal
1
Además, esto se rompe cuando el contenedor externo .block tiene altura mínima en lugar de altura.
Lincoln B
16

Esto es algo que he necesitado hacer muchas veces y una solución consistente aún requiere que agregue un pequeño marcado no semántico y algunos hacks específicos del navegador. Cuando obtengamos compatibilidad con el navegador para CSS 3, obtendrá su centrado vertical sin pecar.

Para una mejor explicación de la técnica, puede consultar el artículo del que lo adapté , pero básicamente implica agregar un elemento adicional y aplicar diferentes estilos en IE y navegadores que admiten position:table\table-cellelementos que no son de tabla.

<div class="valign-outer">
    <div class="valign-middle">
        <div class="valign-inner">
            Excuse me. What did you sleep in your clothes again last night. Really. You're gonna be in the car with her. Hey, not too early I sleep in on Saturday. Oh, McFly, your shoe's untied. Don't be so gullible, McFly. You got the place fixed up nice, McFly. I have you're car towed all the way to your house and all you've got for me is light beer. What are you looking at, butthead. Say hi to your mom for me.
        </div>
    </div>
</div>

<style>
    /* Non-structural styling */
    .valign-outer { height: 400px; border: 1px solid red; }
    .valign-inner { border: 1px solid blue; }
</style>

<!--[if lte IE 7]>
<style>
    /* For IE7 and earlier */
    .valign-outer { position: relative; overflow: hidden; }
    .valign-middle { position: absolute; top: 50%; }
    .valign-inner { position: relative; top: -50% }
</style>
<![endif]-->
<!--[if gt IE 7]> -->
<style>
    /* For other browsers */
    .valign-outer { position: static; display: table; overflow: hidden; }
    .valign-middle { position: static; display: table-cell; vertical-align: middle; width: 100%; }
</style>

Hay muchas formas (hacks) para aplicar estilos en conjuntos específicos de navegadores. Utilicé comentarios condicionales, pero mire el artículo vinculado anteriormente para ver otras dos técnicas.

Nota: Existen formas simples de obtener un centrado vertical si conoce algunas alturas de antemano, si está tratando de centrar una sola línea de texto o en varios otros casos. Si tiene más detalles, tírelos porque puede haber un método que no requiera hacks del navegador o marcado no semántico.

Actualización: Estamos comenzando a obtener una mejor compatibilidad del navegador para CSS3, incorporando tanto la caja flexible como las transformaciones como métodos alternativos para obtener un centrado vertical (entre otros efectos). Consulte esta otra pregunta para obtener más información sobre los métodos modernos, pero tenga en cuenta que la compatibilidad con el navegador aún es incompleta para CSS3.

Prestaul
fuente
Sí, encontré ese artículo hoy y no he podido hacer que funcione para mi situación particular. Quizás necesito investigar eso más a fondo.
jessegavin
¿Quizás pueda publicar el código que está utilizando que no funciona?
Chris Marasti-Georg
¿Sigue siendo la mejor solución para este problema?
ripper234
Ese artículo no parece funcionar en Chrome 23, Firefox 16 e IE 9. Esta respuesta parece ser una mejor solución.
Fernando Correia
No, ese artículo aún funciona en los últimos Chrome y Firefox a partir del 24 de febrero de 2013
OMA
9

Usando el selector de niños, tomé la increíble respuesta de Fadi anterior y la reduje a una sola regla CSS que puedo aplicar. Ahora todo lo que tengo que hacer es agregar el contentCenterednombre de la clase a los elementos que quiero centrar:

.contentCentered {
  text-align: center;
}

.contentCentered::before {
  content: '';
  display: inline-block;
  height: 100%; 
  vertical-align: middle;
  margin-right: -.25em; /* Adjusts for spacing */
}

.contentCentered > * {
  display: inline-block;
  vertical-align: middle;
}
<div class="contentCentered">
  <div>
    <h1>Some text</h1>
    <p>But he stole up to us again, and suddenly clapping his hand on my
      shoulder, said&mdash;"Did ye see anything looking like men going
      towards that ship a while ago?"</p>
  </div>
</div>

CodePen bifurcado: http://codepen.io/dougli/pen/Eeysg

dougli
fuente
Frio. Gracias por compartir. Una nota de precaución es que el *selector funcionará peor que la respuesta aceptada. Puede que no sea un problema, pero vale la pena señalarlo. stevesouders.com/blog/2009/06/18/simplifying-css-selectors
jessegavin
Gracias. Sí, probablemente funcionará peor, pero hoy en día las reglas CSS probablemente no afectan mucho las cosas. Probablemente podamos mejorar esto seleccionando en su > divlugar. calendar.perfplanet.com/2011/…
dougli
Simple y genial Funciona para mi perfectamente.
Lovro
4

El mejor resultado para mí hasta ahora:

div para centrarse:

position: absolute;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
right: 0;
left: 0;
Leo Dimuccio
fuente
Funcionó
3

Puede usar margen automático. Con flex, el div también parece estar centrado verticalmente.

body,
html {
  height: 100%;
  margin: 0;
}
.site {
  height: 100%;
  display: flex;
}
.site .box {
  background: #0ff;
  max-width: 20vw;
  margin: auto;
}
<div class="site">
  <div class="box">
    <h1>blabla</h1>
    <p>blabla</p>
    <p>blablabla</p>
    <p>lbibdfvkdlvfdks</p>
  </div>
</div>
Loïc G.
fuente
display: flex sigue siendo prácticamente una característica experimental; ningún navegador lo admite correctamente todavía
andreszs
1

Para mí, la mejor manera de hacer esto es:

.container{
  position: relative;
}

.element{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

La ventaja es no tener que hacer explícita la altura

Leandro Castro
fuente
0

Esta es mi increíble solución para una divaltura dinámica (porcentual).

CSS

.vertical_placer{
  background:red;
  position:absolute; 
  height:43%; 
  width:100%;
  display: table;
}

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

.inner_placer svg{
  position:relative;
  color:#fff;
  background:blue;
  width:30%;
  min-height:20px;
  max-height:60px;
  height:20%;
}

HTML

<div class="footer">
    <div class="vertical_placer">
        <div class="inner_placer">
            <svg> some Text here</svg>
        </div>
    </div>
</div>  

Intenta esto por ti mismo.

usuario3432605
fuente
0

puede usar la pantalla flexible, como el siguiente código:

.example{
  background-color:red;
  height:90px;
  width:90px;
  display:flex;
  align-items:center; /*for vertically center*/
  justify-content:center; /*for horizontally center*/
}
<div class="example">
    <h6>Some text</h6>
</div>

Hassan Yousefi
fuente