la altura de la línea como porcentaje no funciona

87

Tengo un problema con la altura de la línea que no puedo entender.

El siguiente código centrará una imagen dentro de un div:

CSS

.bar {
    height: 800px;
    width: 100%;
    line-height:800px;
    background-color: #000;
    text-align: center; 
}

.bar img {
    vertical-align: middle;   
}

HTML

<div class="bar">
    <img src="http://27.media.tumblr.com/yHWA4oxH870ulxnoH7CkOSDR_500.jpg" alt="Foo Image" />
</div>

Sin embargo, si cambio la altura de la línea al 100%, la altura de la línea no tiene efecto (o al menos no se convierte en el 100% del div).

Ejemplo jsfiddle

¿Alguien sabe lo que estoy haciendo mal?

Me duele la cabeza
fuente

Respuestas:

194

line-height: 100%significa el 100% del tamaño de fuente para ese elemento, no el 100% de su altura. De hecho, la altura de la línea es siempre relativa al tamaño de fuente, no a la altura, a menos que su valor utiliza una unidad de longitud absoluta ( px, pt, etc).

BoltClock
fuente
3
¡Ah! Siempre son los errores tontos los que me atrapan. ¡Gracias! Aceptaré tu respuesta cuando me lo permita.
Me duele la cabeza
1
Aparentemente, los autores de especificaciones pensaron erróneamente que nadie querría establecer el tamaño de fuente / altura de línea en relación con la altura del elemento ...
Andy
1
@Andy: La buena (?) Noticia es que esto pronto será posible mediante el uso de variables en cascada . Solo unos pocos años de espera ...
BoltClock
@BoltClock ¡ah, genial! Eso sería lindo. ¡Gracias por hacérmelo saber!
Andy
vh es una excepción. En CSS3, si lo configura como 100vh, en realidad funcionará como algunos desarrolladores lo deseen. Sin embargo, tenga en cuenta que no funciona en navegadores antiguos que no son compatibles con CSS3.
Philll_t
97

Sé que esta pregunta es antigua, pero encontré lo que para mí es la solución perfecta.

Agrego este CSS al div que quiero centrar:

div:before {
  content: "";
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}

Esto funciona todo el tiempo y está limpio.

Editar: Solo para completar, uso scss y tengo una combinación útil que incluyo en todos los padres que son hijos directos que quiero tener centrados verticalmente:

@mixin vertical-align($align: middle) {
  &:before {
    content: "";
    display: inline-block;
    height: 100%;
    vertical-align: $align;
    // you can add font-size 0 here and restore in the children to prevent
    // the inline-block white-space to mess the width of your elements
    font-size: 0;
  }
  & > * {
    vertical-align: $align;
    // although you need to know the font-size, because "inherit" is 0
    font-size: 14px;
  }
}

Explicación completa: div:beforeagregará un elemento dentro del div, pero antes de cualquiera de sus hijos. Cuando usamos :beforeo :afterdebemos usar una content:declaración, de lo contrario no pasará nada, pero para nuestro propósito, el contenido puede estar vacío. Luego le decimos al elemento que sea tan alto como su padre, siempre que la altura de su padre esté definida y este elemento sea al menos un bloque en línea. vertical-aligndefine la posición vertical de uno mismo relacionado con el padre, en oposición a text-alignque funciona de manera diferente.

La @mixindeclaración es para usuarios sass y se usaría así:

div {
    @include vertical-align(middle)
}
santiago arizti
fuente
Aunque las otras respuestas son todas correctas, esta es probablemente la solución más limpia y elegante al problema anterior.
mstation
No es la respuesta, ¡pero es muy útil!
Alex
¿Podría explicar en detalle qué está sucediendo allí? No lo entiendo del todo
Valdrinium
1
@Valdrinit Editaré la respuesta con más explicación
santiago arizti
36

Cuando usa el porcentaje como altura de línea, no se basa en el contenedor div, sino en el tamaño de fuente.

locrizak
fuente
22

line-height: 100% sería una manera fácil de centrar elementos verticalmente, si se calculara en relación con el contenedor, pero sería demasiado fácil, por lo que no funciona.

Entonces, en cambio, es solo otra forma de decir la altura de la línea: 1em (¿verdad?)

Otra forma de centrar verticalmente un elemento sería:

.container {
     position:relative;
}
.center {
     position:absolute;
     top:0; left:0; bottom:0; right:0;
     margin: auto;
     /* for horiz left-align, try "margin: auto auto auto 0" */
}
Rolf
fuente
1
Esto no funciona para mí ... no estoy seguro de si me falta algo.
clifgriffin
1
@clifgriffin, intente establecer un ancho y una altura fijos tanto en el contenedor como en el niño "central", asegurándose de que el niño sea más pequeño que el contenedor. El niño debe terminar centrado horizontal y verticalmente dentro del contenedor.
Rolf
22
eso sería demasiado fácil, por lo tanto, no funciona +1 :-)
elipoultorak
@clifgriffin asegúrese de que el contenedor tenga el ancho y la altura correctos, podría centrar todo en un div del mismo tamaño. Este fue el ajuste que tuve que hacer.
David Carrigan
@ user3576887 "eso sería demasiado fácil, por lo tanto, no funciona" es exactamente la razón por la que estoy rechazando esto: hay una muy buena razón por la que no funciona de la manera que le gustaría aquí, y esto no debería ser oscurecido con el propósito de entretenimiento, crítica o lo que se supone que sea.
TheThirdMan
11

puede que no sea bonito, pero funciona y es semántico;

<div class="bar" style="display: table; text-align: center;">
    <img style="display: table-cell; vertical-align: middle;" src="http://27.media.tumblr.com/yHWA4oxH870ulxnoH7CkOSDR_500.jpg" alt="Foo Image" />
</div>

display: table-cell le da a un elemento la capacidad de tabla única para alinearse verticalmente (al menos creo que es único)

Johan Olsson
fuente
Gracias por la respuesta, probé su código pero no parece funcionar para mí.
Me duele la cabeza
hmm, eso es un poco extraño; si puede publicar algo de su código para que pueda verlo más de cerca, podría ayudar más
Johan Olsson
Olsson - Acabo de pegar su código en un JSFiddle y no funcionó. Gracias por el ofrecimiento de ayuda, pero puedo salirme con la mía estableciendo una altura de línea absoluta por ahora. Si eso cambia, analizaré más a fondo tu respuesta. ¡Gracias de nuevo por la ayuda!
Me duele la cabeza
6

Esta es una respuesta muy tardía, sin embargo, en los navegadores modernos, asumiendo que el elemento principal también tiene el 100% de la altura de la pantalla, puede usar la vhunidad de ventana gráfica. VIOLÍN

line-height: 100vh;

Soporte de navegador

FelisPhasma
fuente
Un uso legítimo poco común de vh en lugar de%.
cytsunny
1

Esta solución funciona en IE9 y superior. Primero establecemos la posición superior del niño al 50% (en el medio del padre). Luego, usando la translateregla, mueva al niño a la mitad de su altura real. El principal beneficio es que no necesitamos definir la altura del niño, el navegador la calcula de forma dinámica. JSFiddle

.bar {
    height: 500px;
    text-align: center;
    background: green;
}
.bar img {
    position: relative;
    top: 50%;
    transform: translate(0, -50%);
}
Webars
fuente
1

Un enfoque más moderno es usar flexbox para esto, es más simple y limpio. Sin embargo, flexbox es un paradigma completamente diferente de lo que inline-block, floatoposition solía ser.

Para alinear elementos dentro de .parentusted:

.parent {
  display: flex;
  align-items: center;
}

Eso es todo. Niños deflex padres se convierten automáticamente en elementos secundarios flexibles.

Debería leer más sobre flexbox, un buen lugar para comenzar es esta hoja de trucos: https://css-tricks.com/snippets/css/a-guide-to-flexbox/

santiago arizti
fuente
0

Puede establecer la altura de la línea en función de la altura de ese elemento. Si la altura del elemento 200px significa que debe establecer la altura de la línea en 200px para centrar el texto.

span {
  height: 200px;
  width: 200px; 
  border: 1px solid black;
  line-height: 200px; 
  display: block;
}
<span>Im vertically center</span>

Raja
fuente
0

Esta es la solución moderna en la que necesita establecer el siguiente CSS en el contenedor div o div externo.

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

Se puede aplicar otra solución siguiente al elemento que desea centrar verticalmente. Tenga en cuenta que el div externo o contenedor debe ser

.inner-div {
    position: absolute;
    top: 50%; 
    left: 50%;
    transform: translate(-50%,-50%);
    text-align: center;
}

Tenga en cuenta que la posición div externa o del contenedor debe ser relativa.

Asraf Ud Duha
fuente