jueves, 30 de abril de 2009

Centrar verticalmente una imagen en un div

Aparentemente una cosa tan trivial como esa tiene un poco más de miga de lo que parece, y buscando soluciones se encuentran muchas divagaciones y ejemplos interminables.

La primera idea es usar el atributo vertical-align, pero sólo es válido para alinear la imagen con el texto adjacente. Sin embargo, se puede usar una solución simple basada ese atributo.

Si definimos el line-height del div igual a su altura y le ponemos un espacio en blanco delante de la imagen para que tenga una referencia donde alinearse, ya lo tenemos:

<div style="border: 1px solid #AA0000; text-align: center; line-height: 100px; width: 100px; height: 100px;">
&nbsp;<img style="vertical-align: middle;" src="http://www.blogger.com/logo.gif" />
</div>




Actualizacion 04/05/2009: Fer propone en los comentarios posibles alternativas a mi solución. Gracias!


Actualización 12/06/2009: He probado en Browsershots esta solución y los resultados son que funciona en

- Navegadores basados en Gecko (todas las versiones probadas de Firefox, Seamonkey, ...)
- Navegadores baseados en KHTML/Webkit (todas las versiones probadas de Konqueror, Safari, Chrome, ...)
- Todas las versiones de Opera a partir de la 7.54 incluida la 10 beta
- Internet Explorer 8.0

Y no funciona en:
- Versiones de IE inferiores a la 8.0 (7.0, 6.0, 5.5)
- Avant
- Dillo


Actualización 7/10/2009: En CodeProject dan una solución basada en javascript

Actualización 4/5/2011: 2 años después sigue dando guerra el mismo problema y en los comentarios apuntan un enlace que resuelve un caso particular. Gracias

http://www.jakpsatweb.cz/css/css-vertical-center-solution.html

14 comentarios:

  1. Hola,

    Es ingeniosa la idea, pero eso de meter el espacio por delante... Yo prefiero una solución más "css", sin tener que modificar el marcado. Sería declarar el contenedor con position:relative, y el hijo (en este caso la imagen) con position:absolute. Luego, al hijo le asignas top:50% y left:50%, y para que queden totalmente centrados, un margin-top negativo igual a la mitad de su altura, y un margin-left negativo igual a la mitad de su ancho. Es decir:

    div{
    position: relative;
    }

    img{
    position: absolute;
    top: 50%;
    left: 50;
    width: 100px;
    height: 100px;
    margin-top: -50px;
    margin-left: -50px;
    }

    Si la imagen está situada con más elementos "inline", sería bueno asignarle tambien un display:block;

    Saludos!!

    ResponderEliminar
    Respuestas
    1. Hola,
      Una duda soy nuevo con lo del css,como se enlazaria desde un archivo externo a el archivo html.
      Un saludo!

      Eliminar
  2. Hola Fer

    Gracias por el comentario.
    Yo tambien estaba buscando una solución más 'css' como tu comentas, pero al final elegí la que he puesto porque era para usarlo en un slider de imagenes (concretamente en http://jqueryfordesigners.com/coda-slider-effect/), donde se iban a utilizar imagenes de diferente tamaño y es la solución más simple que he encontrado sin tener que añadir estilos en cada una de las imágenes utilizadas.

    Si es para una sola imagen o para varias del mismo tamaño, sin duda tu solución es más elegante.

    ResponderEliminar
  3. Interesante reto... Voy a ver si se me ocurre algo mejor!

    No te dije antes: me encanta tu blog, te sigo desde hace bastante por el feed!! un saludo y sigue así

    ResponderEliminar
  4. Pues nada, otra manera.

    Esta tiene la pega que todos los hijos tienen que ser display:block.

    Al container le pones, simplemente display:table-cell, y al hijo display: block. Al no ser display:inline la imagen ya no te servirá el text-align:center para centrarla verticalmente... tendras que usar: margin:0 auto. Quedaría así:

    div{
    display:table-cell;
    }

    img{
    display: block;
    margin: 0 auto;
    }

    Imagino que no funcionará en IE... lo cual seguro que no extraña a nadie, jajaja!

    Un saludo!

    ResponderEliminar
  5. Pues no me funciona ninguna de las propuestas. Quiero centrar veticalmente imágenes de una galería y he visto códigos de todo tipo. Lo que más se aproxima es el table y table-cell pero claro necesito compatibilidad con Iexplorer. Que aunque no guste el 80% de los navegadores.

    Salu2!

    ResponderEliminar
  6. He actualizado la entrada con un listado completo de browsers en los que funciona. Parece que IE con la versión 8 empieza a seguir estándares y lo renderiza bien, pero no funciona en versiones anteriores.... así que no tengo una solución para IE7 :(

    De todas formas, lo de un 80% es un poco exagerado. Los últimos datos son que IE7 tiene un 40% y IE6 un 17%, y ambos van bajando día a día a favor de IE8

    http://marketshare.hitslink.com/browser-market-share.aspx?qprid=2

    Aún así, es un porcentaje lo suficientemente importante para tenerlos en cuenta

    ResponderEliminar
  7. a mi, lo que se propone en este post me ha funcionado de maravillas. Gracias!

    Lo que importa no es el css sinó sus resultados...

    ResponderEliminar
  8. exite un problema con este codigo y es que si quiero centrar un contenido pero el alto resulta ser las grande que el de la pantalla que estoy viendo la parte superior de la web se pierde.. aca les dejo un tuto que me saco del apuro...

    http://www.jakpsatweb.cz/css/css-vertical-center-solution.html

    ResponderEliminar
  9. intentando a ver

    http://www.openzona.com

    ResponderEliminar
  10. Pues a mí me funcionó de maravilla... :D muchas gracias por el post...

    ResponderEliminar
  11. Exelente tip !!!

    div {
    width:100px;
    height:132px;
    line-height:132px;
    text-align:center;
    }
    img {
    vertical-align: middle;
    }

    ResponderEliminar