Cómo centrar el div verticalmente dentro del div padre absolutamente posicionado


146

Estoy tratando de obtener un contenedor azul en medio del rosa, sin embargo, parece vertical-align: middle;que no funciona en ese caso.

<div style="display: block; position: absolute; left: 50px; top: 50px;">
    <div style="text-align: left; position: absolute;height: 56px;vertical-align: middle;background-color: pink;">
        <div style="background-color: lightblue;">test</div>
    </div>
</div>

Resultado:

ingrese la descripción de la imagen aquí

Expectativa:

ingrese la descripción de la imagen aquí

Sugiera cómo puedo lograr eso.

Jsfiddle


1
¿Hay alguna razón por la que estás usando en position: absolutetodas partes?
Vucko

los vertical-align: middle;trabajos con display: inline-blocko diseño de tabla
ctf0


@Vucko sí, eso es un prerrequisito, ya que esta es solo una versión simplificada de un diseño muy complejo, pero la posición absoluta en ambos divs superiores es la clave.
Vladimirs

@Vladimirs Solo puedo pensar en margin-top: calc((56px - 16px) / 2)dónde 56px - parent height, 16px - element height/font-size- JSFiddle
Vucko

Respuestas:


332

En primer lugar, tenga en cuenta que vertical-alignsolo es aplicable a celdas de tabla y elementos de nivel en línea.

Hay dos formas de lograr alineaciones verticales que pueden o no satisfacer sus necesidades. Sin embargo, te mostraré dos métodos de mis favoritos:

1. Usando transformytop

.valign {
    position: relative;
    top: 50%;
    transform: translateY(-50%);
    /* vendor prefixes omitted due to brevity */
}
<div style="position: absolute; left: 50px; top: 50px;">
    <div style="text-align: left; position: absolute;height: 56px;background-color: pink;">
        <div class="valign" style="background-color: lightblue;">test</div>
    </div>
</div>

El punto clave es que un valor de porcentaje en topes relativo al del heightbloque contenedor; Mientras que un valor porcentual en transforms es relativo al tamaño del cuadro en sí (el cuadro delimitador).

Si experimenta problemas de representación de fuente (fuente borrosa), la solución es agregar perspective(1px)a la transformdeclaración para que se convierta en:

transform: perspective(1px) translateY(-50%);

Vale la pena señalar que CSS transform es compatible con IE9 + .

2. Usando inline-block(pseudo-) elementos

En este método, tenemos dos inline-blockelementos hermanos que están alineados verticalmente en el medio por vertical-align: middledeclaración.

Uno de ellos tiene uno heightde 100%sus padres y el otro es nuestro elemento deseado cuyo que queríamos alinear en el medio.

.parent {
    text-align: left;
    position: absolute;
    height: 56px;
    background-color: pink;
    white-space: nowrap;
    font-size: 0; /* remove the gap between inline level elements */
}

.dummy-child { height: 100%; }

.valign {
    font-size: 16px; /* re-set the font-size */
}

.dummy-child, .valign {
    display: inline-block;
    vertical-align: middle;
}
<div style="position: absolute; left: 50px; top: 50px;">
    <div class="parent">
        <div class="dummy-child"></div>
        <div class="valign" style="background-color: lightblue;">test</div>
    </div>
</div>

Finalmente, debemos usar uno de los métodos disponibles para eliminar la brecha entre los elementos de nivel en línea .


Gracias por estos consejos útiles. Estaba funcionando para mi proyecto. Buen trabajo.
Sedat Kumcu

Para el primer valignelemento del método debe serdisplay: block
Oleg

transform: translateY(-50%);Nunca he visto esto antes, pero funciona a la perfección. Protector de la vida real.
Benny Bottema

55

utilizar este :

.Absolute-Center {
    margin: auto;
    position: absolute;
    top: 0; left: 0; bottom: 0; right: 0;
}

consulte este enlace: https://www.smashingmagazine.com/2013/08/absolute-horizontal-vertical-centering-css/


¿Cómo no es esta la solución principal? ¡Tan fácil y funciona!
Mason

21
Tenga en cuenta que la heightpropiedad debe estar definida (en px, em, etc.) para que esto funcione.
Vaidas

¿Qué pasa si tengo múltiples divs dentro del padre? ¿No se colocarían todos uno encima del otro?
psykid

no funciona si hay un niño más en el mismo nivel con "centro absoluto"
Pascut

18

Usa flex blox en tu div posicionado para centrar su contenido.

Ver ejemplo https://plnkr.co/edit/wJIX2NpbNhO34X68ZyoY?p=preview

.some-absolute-div {    
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;

  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  justify-content: center;

  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -moz-align-items: center;
  align-items: center;
}

11

Centro vertical y horizontalmente:

.parent{
  height: 100%;
  position: absolute;
  width: 100%;
  top: 0;
  left: 0;
}
.c{
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
}

3

Puedes usar display:table/table-cell;

.a{
   position: absolute; 
  left: 50px; 
  top: 50px;
  display:table;
}
.b{
  text-align: left; 
  display:table-cell;
  height: 56px;
  vertical-align: middle;
  background-color: pink;
}
.c {
  background-color: lightblue;
}
<div class="a">
  <div  class="b">
    <div class="c" >test</div>
  </div>
</div>


Gracias, su ejemplo funciona perfecto, sin embargo, .bfalta lo position: absolute;que es importante para mostrar otras cosas que no incluí para mantener el código más claro. Sé que no tiene sentido tener-celda de la tabla con posición absoluta, pero quizá no hay otro enfoque que permita retener position: absolute;en tanto .ay .bclases?
Vladimirs

Si a es una posición absoluta yb (el niño) le da su tamaño, b está en posición absoluta hacia el resto del contenido. a menos que se suponga que a permanecer sin tamaño no entiendo el propósito de absoluto dentro de absoluto?
G-Cyrillus

1

Aquí hay una manera simple de usar el objeto Top.

Por ejemplo: si el tamaño absoluto del elemento es 60px.

.absolute-element { 
    position:absolute; 
    height:60px; 
    top: calc(50% - 60px);
}

2
Usar calces útil, aunque esto debería ser top: calc(50% - 30px)para que realmente esté centrado.
brainbag

1

Una solución simple adicional

HTML:

<div id="d1">
    <div id="d2">
        Text
    </div>
</div>

CSS:

#d1{
    position:absolute;
    top:100px;left:100px;
}

#d2{
    border:1px solid black;
    height:50px; width:50px;
    display:table-cell;
    vertical-align:middle;
    text-align:center;  
}

0

Verifique esta respuesta a un problema similar.

Esta es, con mucho, la forma más fácil que he encontrado.

https://stackoverflow.com/a/26079837/4593442

NOTA. Solía pantalla: -webkit-flex; en lugar de mostrar: flex;para probar dentro de safari.

NOTA. Solo soy un novato, comparto la ayuda de alguien que tiene una experiencia clara.


0

Puede hacerlo utilizando display:table;en div padre y display: table-cell; vertical-align: middle;en div hijo

<div style="display:table;">
      <div style="text-align: left;  height: 56px;  background-color: pink; display: table-cell; vertical-align: middle;">
          <div style="background-color: lightblue; ">test</div>
      </div>
  </div>


3
es posible que su respuesta sea buena, pero puede mejorarla mucho agregando una descripción de lo que hace su código ...
DaFois
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.