Consejo rápido: cómo usar el elemento “picture” de HTML5 para imágenes responsivas

() translation by (you can also view the original English article)
Las imágenes son notoriamente uno de los aspectos más desafiantes del diseño web responsivo. Hoy veremos como el elemento <picture>
, una solución al problema de imágenes responsivas, puede ser usado ahora mismo.
Primero, El Problema
Los días del diseño web con fixed-width y pixel perfecto quedaron atrás. En el presente el día de los monitores widescreen, internet TVs, tabletas de múltiples medidas y teléfonos inteligentes, nuestros diseños ahora tienen que adecuarse desde los 320px hasta potencialmente tan alto como 7680px de ancho.
Junto con este panorama multi-resolución viene la necesidad de que las imágenes se expandan o encojan para encajar en estos requerimientos que tanto cambian. Esto puede probar que esto es un problema dado que con la excepción de los gráficos en vector, la basta mayoría de las imágenes tienen un anchura en pixeles especificos que no cambia.
Entonces, ¿Qué hacemos?
La Solución Actual y la Más Común
Como regla general, encontrarás lo siguiente en el CSS de casi cualquier sitio responsivo:
1 |
img { |
2 |
max-width: 100%; |
3 |
height: auto; |
4 |
} |
Este código usa un max-width: 100%;
para asegurar que las imágenes nunca vayan más allá del contenedor padre. Si el contenedor padre se encoge más allá de la anchura de la imagen, la imagen se encogerá junto con el. El height: auto;
asegura que la relación de aspecto se preserve cuando esto ocurra.



Resuelve el problema con respecto a que nos deja mostrar la misma imagen en diferentes circunstancias. Pero no nos deja especificar diferentes imágenes para diferentes circunstancias.
Una nueva Solución: <picture>
<picture>
es un nuevo elemento que está por ser parte del HTML5.
Nos llevará a que el proceso de poner imágenes responsivas sea como el que actualmente los elementos de <audio>
y <video>
tienen. Te dejará poner múltiples etiquetas source
, cada una especificando diferentes nombres de archivo de imágenes junto con condiciones en las que cada una será cargada.
Te dejara cargar una imagen totalmente diferente dependiendo en:
- El resultado de media queries ej. viewport height, width, orientation
- Densidad de Pixel
Esto significa que puedes:
- Cargar imágenes de tamaño de archivo apropiado, haciendo el mejor uso de la banda ancha.
- Cargar imágenes recortadas a una diferente relación de aspecto para ajustarse a los cambios en el layout a diferente anchura.
- Cargar imágenes con alta resolución para pantallas de alta densidad de Pixel



¿Cómo funciona el elemento <picture>
?
Los pasos básicos para trabajar con <picture>
son:
- Abre y cierra la etiqueta de
<picture></picture>
- Entre esas etiquetas crea un elemento
<source>
para cada query que quieras ejecutar. - Agrega un atributo
media
que contenga tu query con cosas como alto de ventana, ancho, orientación etc.. - Agrega un atributo
srcset
con el nombre de archivo correspondiente de la imagen a cargar. - Agrega nombres de archivos extra a tu atributo
srcset
si quieres proveer para diferentes densidades de pixel, ej. Pantallas retina. - Agrega un elemento
<img>
como fallback.
Aquí esta un ejemplo que verifica si la ventana es menor que 768px, si lo es, entonces carga una imagen más pequeña:
1 |
<picture>
|
2 |
<source srcset="smaller.jpg" media="(max-width: 768px)"> |
3 |
<source srcset="default.jpg"> |
4 |
<img srcset="default.jpg" alt="My default image"> |
5 |
</picture>
|
Notaras que el syntax usado en el atributo media
es el mismo al que estas acostumbrado en media queries de CSS. Puedes verificar lo mismo, puedes hacer queries para max-width
, min-width
, max-height
, min-height
, orientation
y demás.
Puedes usar estas verificaciones para hacer cosas como cargar versiones de una imagen apaisada o vertical dependiendo de la orientación del dispositivo, y también puedes mezclar queries del tipo size al mismo tiempo. Por ejemplo:
1 |
<picture>
|
2 |
<source srcset="smaller_landscape.jpg" media="(max-width: 40em) and (orientation: landscape)"> |
3 |
<source srcset="smaller_portrait.jpg" media="(max-width: 40em) and (orientation: portrait)"> |
4 |
<source srcset="default_landscape.jpg" media="(min-width: 40em) and (orientation: landscape)"> |
5 |
<source srcset="default_portrait.jpg" media="(min-width: 40em) and (orientation: portrait)"> |
6 |
<img srcset="default_landscape.jpg" alt="My default image"> |
7 |
</picture>
|
El código de arriba carga una versión recortada de manera apaisada y más chica para un dispositivo mas chico y de orientación apaisada.
Si el dispositivo tiene una orientación vertical entonces carga una versión recortada verticalmente, a un tamaño mas chico para un dispositivo más chico o de tamaño grande para un dispositivo más grande.
Si quieres proveer diferentes versiones de resolución de tus imágenes para pantallas de alta densidad, lo puedes hacer agregando nombres de archivos extra al atributo srcset
. Por ejemplo, veamos nuestro primer snippet del código de arriba agregando el manejo para resolución 2x para pantallas Retina:
1 |
<picture>
|
2 |
<source srcset="smaller.jpg, smaller_retina.jpg 2x" media="(max-width: 768px)"> |
3 |
<source srcset="default.jpg, default_retina.jpg 2x"> |
4 |
<img srcset="default.jpg, default_retina.jpg 2x" alt="My default image"> |
5 |
</picture>
|
El media query sigue siendo evaluado primero para que puedas controlar las dimensiones de la imagen que aparecerá en pantalla. Después de la densidad de pixel de la pantalla será verificada y si altas densidades cuentan con soporte y son habilitados por las preferencias del usuario, la versión de alta densidad de la imagen será cargada.
Usando <picture>
hoy en día
Actualmente la implementación nativa para <picture>
está en desarrollo para Chrome, Firefox y Opera. En el futuro será de esperarse que habrá un soporte más abierto por otros navegadores. Pero por el momento soporte para este elemento todavía está por llegar.
Mientras eso pasa, no tienes que esperar si quieres empezar a usar <picture>
ahora. Simplemente tienes que usar Picturefill 2.0; un polyfill provisto por la gente inteligente de Filament Group.



Después de descargar el archivo picturefill.js a tu proyecto puede ser implementado simplemente cargándolo en la sección head de tu sitio:
1 |
<script src="picturefill.js"></script> |
También hay una opción de cargar el script asincrónicamente para agregar eficiencia, lo cual puedes leer más en la Documentación de Picturefill.
Con el script ya cargado el elemento <picture>
funcionará como lo he explicado, con sólo unas limitaciones.
Limitaciones de Picturefill
IE9
Picturefill funciona bien con otras versiones de IE9, sin embargo IE9 no reconoce los elementos source
que estén envueltos dentro de una etiqueta picture
. Para arreglarlo, con condiciones envuelve tus elementos source en etiquetas de video
las cuales los hará visibles a IE9 por ejemplo:
1 |
<picture>
|
2 |
<!--[if IE 9]><video style="display: none;"><![endif]-->
|
3 |
<source srcset="smaller.jpg" media="(max-width: 768px)"> |
4 |
<source srcset="default.jpg"> |
5 |
<!--[if IE 9]></video><![endif]-->
|
6 |
<img srcset="default.jpg" alt="My default image"> |
7 |
</picture>
|
Android 2.3
Así como con IE9, Android 2.3 no puede ver los elementos source
dentro de un elemento picture
. Sin embargo, puede entender el atributo srcset
cuando es usado en una etiqueta img
regular. Asegurate siempre de incluir un elemento de respaldo img
con el nombre de archivo por default en el atributo srcset
para Android 2.3 y otros navegadores que puedan tener el mismo problema.
Requiere JavaScript y Soporte Nativo de Media Queries
Siendo esta una solución basada en JavaScript, requiere que JavaScript esté habilitado en el navegador. Picturefill 2.0 no provee una solución "no-js" porque si lo hiciera, multiples imágenes aparecerían cuando el soporte nativo para <picture>
haya sido lanzado. Sin embargo, no tendrías la opción de usar Picturefill 1.2 si una solucion "no-js" es lo que necesitas.
El otro requerimiento de Picturefill es el soporte nativo para Media queries, para que los queries en el atributo media
funcionen. Los navegadores modernos tienen soporte para media queries siendo IE8 hacia atrás los únicos navegadores que no tienen soporte para media queries con una pequeña cantidad de usuarios.
Posibles Peticiones HTTP Extra
En navegadores con soporte nativo para srcset
, pero no aún para picture
, es posible que el nombre de archivo especificado en el elemnto img
de respaldo sea pedido antes que una mejor imagen que encaje del source
sea determinada.
Esto es sólo un problema temporal que se irá cuando la implementación nativa de picture
sea lanzada.
Más Información
- Lee más acerca de Picturefill 2.0 y descárgalo para tu proyecto en la página de Picturefill
- Recive mayor información del elemento
<picture>
en responsiveimages.org.
Prueba <picture>
en tu proyecto ahora y ¡dinos lo que piensas!
¡Sé el primero en conocer las nuevas traducciones–sigue @tutsplus_es en Twitter!