Imágenes responsive con HTML y CSS

reset css

Las imágenes y el diseño web responsive parece que no se llevan muy bien, porque encajar elementos con tamaños fijos en otros con tamaños relativos no siempre es sencillo, pero por suerte tenemos varias posibles soluciones para las imágenes.

Hay dos formas distintas de afrontar el problema, que la imagen tenga un tamaño relativo en lugar de uno fijo y así se adaptará a los diferentes tamaños de pantalla o bien tener distintas versiones de las imágenes para los distintos tamaños posibles.

Como suele ser habitual dependerá de cada caso concreto cual es la mejor solución. Por ejemplo en una página en la que tengamos 20 imágenes de alta resolución sería conveniente tener diferentes versiones de las imágenes para que el tiempo de carga sea más rápido en dispositivos en los que no vamos a poder aprovechar tanta resolución y que probablemente tengan conexiones más lentas, pero si tenemos un par de imágenes de 10k pues tener que poner múltiples versiones de las imágenes no nos va a ofrecer prácticamente ninguna mejora en el rendimiento por lo que podemos optar por una solución más «sencilla».

Imágenes responsives con unidades relativas

En lugar de utilizar un tamaño fijo en píxeles para las imágenes podemos usar un porcentaje directamente pero de este modo el tamaño de la imagen fluye con el tamaño de su contenedor y puede hacer que la imagen crezca demasiado y se llegue a ver pixelada, por este motivo suele dar mejor resultado usar el max-width con el porcentaje en lugar del with directamente, porque garantizamos que cuando el espacio disminuye la imagen también lo hace pero si aumenta la imagen solo aumentará hasta su tamaño y siempre se verá bien.


.img-responsive {
    max-width: 100%;
    height: auto;
}

Con esta sencilla clase ya podemos hacer las imágenes responsives y si lo combinamos con el uso de imágenes vectoriales pues ya tenemos hecho todo el trabajo, y sino continuamos…

Imágenes responsives, una imagen distinta para cada situación

Defiendo el tamaño de las imágenes en base a porcentajes conseguimos que nuestro objetivo de que se adapten a los diferentes tamaños de pantalla, pero la pega de este método es que cargamos la misma imagen independientemente de que la pantalla sea 4k o de 320px y más que por el simple hecho de que estemos cargando una imagen y mostrándola al 10% de su tamaño por ejemplo es lo que ocupa esa imagen y lo que ocuparía una imagen que solo ya tuviese ese tamaño del 10%.

Para conseguir esa eficiencia tanto en tiempo de carga como en el tamaño que ocupe nuestra web necesitamos el siguiente método.

Cambiar el tamaño de una imagen dependiendo del ancho de pantalla

Las imágenes son de los factores que más penalizan el tiempo de carga de las páginas y cuando al menos se pueden disfrutar porque la resolución del dispositivo lo permite pues no hay problema pero si por ejemplo tengo una imagen de 3648×2056 que ocupa 1,77Mb pues solo la van a poder ver completa los usuarios que tengan una pantalla 4k y obviamente van a ser un porcentaje bastante pequeño, por lo tanto puedo ir creando imágenes más pequeñas para las diferentes resoluciones y así no hacemos descargar una imagen tan pesada a los usuarios con resoluciones bajas.

Para el ejemplo voy a utilizar los tamaños de imagen que me genera automáticamente wordpress, 1024×577 (124Kb) y 300×169 (14,2Kb) además del tamaño original. Y simplemente tenemos que usar dos atributos (srcset y sizes) de la etiqueta img para que el navegador decida cuál es el tamaño adecuado y descargue solo ese.

Bueno en realidad con srcset es suficiente, tenemos que indicar la lista de imágenes junto con el tamaño de pantalla para el que son adecuadas separándolas por comas y listo, el navegador seleccionará la imagen que mejor se ajuste a la pantalla.


<img 
  srcset="http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/vega_llos_nieve-300x169.jpg 600w,
      http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/vega_llos_nieve-1024x577.jpg 1920w,
      http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/vega_llos_nieve.jpg 3840w"
  src="http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/vega_llos_nieve-1024x577.jpg" 
  alt="Vega de Llos con nieve (Valdeón)"/>

Por ejemplo en mi caso se queda con la de 1024×577 porque es una pantalla simplemente fullhd y el tamaño original es excesivo, pero ese tamaño es mayor que el contenedor y descuadra el diseño, es decir, el navegador «es inteligente» pero no hace magia, tenemos que seguir controlando nuestros estilos.

Vega de Llos con nieve (Valdeón)

Con sizes podemos hacerlo directamente en la imagen, por ejemplo con el siguiente ejemplo con el siguiente código hacemos que si el tamaño de la pantalla es menor de 320px la imagen ocupe solo 300px, si es menor de 1920 ocupe solo 844px y si no pues que el ancho sea 2000px.

Asi podemos ajustar el tamaño de la imagen en función de la resolución, cuando usamos sizes el tamaño de imagen que se usa es el que más se ajuste al tamaño definido en este atributo, por lo tanto, si en el sizes tuviésemos (max-width: 1980px) 150px la imagen que se cargaría sería la 300px aunque por resolución de pantalla la de 1024px sea mejor porque 150 está más próximo de 600w que de 1920w. Cuando usando ambos atributos conjuntamente podemos poner en el srcset el tamaño de la imagen y así garantizamos que la imagen sea la que más se ajusta al tamaño con el que la vamos a mostrar, ahora en mi caso se muestra la imagen de 1024px pero ocupando solo 844px.


<img 
  srcset="http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/vega_llos_nieve-300x169.jpg 300w,
      http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/vega_llos_nieve-1024x577.jpg 1024w,
      http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/vega_llos_nieve.jpg 3840w"
  sizes=" (max-width: 600px) 300px,
        (max-width: 1980px) 844px,
      2000px"
  src="http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/vega_llos_nieve-1024x577.jpg" 
  alt="Vega de Llos con nieve (Valdeón)"/>

Vega de Llos con nieve (Valdeón)

Selección de la imagen en función del devicePixelRatio

Otra de los puntos a tener en cuenta a la hora de utilizar imágenes es la densidad de píxeles de las pantallas, que al igual que los tamaños también afecta a la forma en la que se van a visualizar.

Cuando mayor es la densidad de pixeles de un pantalla las imágenes se ven más pequeñas, por ejemplo la imagen de 300px de ancho en un TV FullHD puede ser como una mano mientras que en un móvil con la misma resolución será como una uña por que la densidad de píxeles es mucho mayor (los pixeles son más pequeños).

El devicePixelRatio es la relación entre el tamaño de los píxeles del dispositivo y los píxeles CSS o píxeles de referencia (Device Independent Pixel) y en función de este valor el navegador utilizará el número de píxeles reales de la pantalla correspondientes, por ejemplo en una pantalla HiDPI o en una Retina si hablamos de Apple en la que la relación sea 2x una imagen de 100px utiliza 200px reales de la pantalla.

Y como la idea de las pantallas retina o cualquier otra pantalla HiDPI es que se vean las cosas más nítidas, por eso para este tipo de pantallas necesitamos utilizar imágenes con mayor resolución y que de esta forma ocupen el mismo número de píxeles físicos el concepto es sencillo, vamos a ver cómo conseguirlo.

Para esto también hacemos uso de srcset pero en este caso no es necesario sizes, simplemente tenemos que indicar las rutas a las imágenes con las distintas resoluciones y después de cada nombre indicar la proporción a la que se corresponde con Nx y separándolo del nombre de la imagen por un espacio, como antes las diferentes imágenes se separan con la coma «,». Si no se indica ningún multiplicador se usa el 1x que es la densidad estándar.


<img 
  srcset="http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/icono-alerta-50x50.png,
      http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/icono-alerta100x100.png 2x,
      http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/icono-alerta200x200.png 4x"
  src="http://programandoointentandolo.com/wordpress/wp-content/uploads/2017/10/icono-alerta-50x50.png" 
  alt="Cuidado!!!"/>

De entre las 3 imágenes el navegador decidirá cuál es la más adecuada y por si el navegador no lo soporta o no se adapta a ninguno de los ratios indicados mantenemos el atributo src.

Cuidado!!!Cuidado!!!Cuidado!!!

Y la imagen que el navegador determina que es la adecuada para tu pantalla es:

Cuidado!!!

Con la función window.devicePixelRatio podemos obtener esta relación en javaScript ya sea simplemente por curiosidad o para utilizarla para algún fin aunque con las @media queries de CSS (@media screen and (min-resolution: 2dppx) {...}, @media screen and (min-resolution: 192dpi) {...}) será suficiente normalmente y dejamos cada cosa en su sitio.