Cómo usar la etiqueta Picture para crear imágenes responsive, un nuevo elemento de HTML5 que permite que las imágenes y su resolución se adapten a todo tipo de pantallas.
Uno de los principales componentes con los que tenemos que lidiar en toda web son las imágenes y su tratamiento para producir sitios adaptables es clave. Para adaptar una imagen muchas veces es suficiente con asignarle con CSS una anchura relativa, de modo que si su contenedor aumenta de tamaño, la imagen también aumentará.
La problemática sobre todo la encontramos con imágenes pesadas, como fotografías, donde la elección de su tamaño y calidad dependerá de la pantalla donde se visualicen. Si pensamos que esa imagen debe mostrarse en pantallas grandes, tendremos que generar un archivo de gran tamaño. Pero ese archivo de proporciones grandes representa un desperdicio de transferencia si pensamos que esa imagen se va a ver en un móvil con una pantalla realmente pequeña.
Lo ideal es poder distribuir imágenes acorde con el tamaño de la pantalla y no solamente sus pulgadas, sino a veces también la densidad de píxeles importa. En el pasado aparecieron algunos plugin Javascript especiales para hacer imágenes responsive, también CSS hacks o incluso servicios web, que nos permitían discriminar por el tamaño de la pantalla, o velocidad, entregando al navegador el archivo con el fichero de imagen más adecuado dependiendo de los diferentes escenarios. Soluciones propietarias que acabarán de ser sustituidas por la nueva etiqueta PICTURE.
El objetivo, en resumidas cuentas es el siguiente:
- Poder indicar una imagen y varios archivos de alternativa para distintos escenarios: pantallas pequeñas, medianas o grandes, velocidades de conexión, etc.
- Que el navegador sólo descargue una de las imágenes posibles y no todas. O sea, si una imagen tiene tres alternativas de tamaños, se le entregue al navegador solamente una de ellas, ahorrando la descarga de los otros tamaños alternativos que no necesita.
Elemento PICTURE
El elemento PICTURE en sí no representa contenido alguno, sirve sólo como un contenedor para escribir varias imágenes y que sea el propio navegador el que elija la más apropiada en cada caso.
Para indicar las imágenes dentro de PICTURE se indicarán varias etiquetas SOURCE. Se parece algo a la etiqueta VIDEO o AUDIO, en el que se pueden indicar varios archivos diferentes, de modo que el navegador localice aquel que consiga reproducir con su conjunto de codecs. Pero en este caso en vez de vídeos se indicarán archivos gráficos.
Además, a modo de fallback, dentro de la etiqueta PICTURE se encontrará una imagen corriente, con la etiqueta IMG, que será representada por todo navegador que todavía no implemente el tag HTML5 PICTURE.
Para que cada navegador sepa cuál es el archivo más interesante según sus condiciones a las etiquetas SOURCE se les debe escribir un atributo "media", indicando una mediaquery CSS que debería cumplirse para usar ese archivo fuente.
Es muy sencillo. Lo veremos mejor a la vista del siguiente ejemplo:
<picture>
<source media="(min-width: 900px)" srcset="grande.png">
<source media="(min-width: 550px)" srcset="media.png">
<img src="archivo-pequeno.jpg">
</picture>
Este código funcionará en todos los navegadores. Los que estén familiarizados con el tag PICTURE mostrarán la imagen adecuada en cada caso. Los que no estén familiarizados simplemente mostrarán la imagen que se haya indicado en IMG.
SOURCE element
Ahora veamos el elemento SOURCE, usado para indicar cada una de las varias imágenes.
Básicamente nos permite indicar varios archivos gráficos. El navegador irá leyéndolos uno a uno, desde el primero hasta el último, en orden de colocación, hasta que encuentre uno que sea posible usar. Usará el primero que sea posible, descartando los demás que pueda haber por debajo.
Incluye los siguientes atributos.
srcset:
Contiene el archivo de imagen que debe visualizarse. Es un campo requerido.
<source media="(max-width: 300px)" srcset="archivo-hasta-300px.jpg">
Pero además, podríamos indicar varias alternativas de imágenes, separadas por comas, para indicar versiones de la misma para distintas densidades de píxeles. Esto es muy interesante para los móviles modernos, que tienen pantallas con viewport pequeños pero que realmente tienen muchos más píxeles de los que aparentan. También para los monitores "retina" u otras marcas que tienen densidades de píxeles distintas. Para marcar la densidad de píxeles indicamos algo como "2x" o "3x" dependiendo si duplican o triplican la densidad estándar. (Si no se indica nada se entiende que ese archivo es para la densidad normal de píxeles.
<source media="(min-width: 900px)" srcset="foto.jpg, foto-hd.jpg x2"
En el caso anterior se distribuirá la imagen foto.jpg en pantallas con densidad de píxeles común y foto-hd.jpg para las densidades de píxeles mayores.
Media:
Este atributo soporta cualquier media query que podrías usar en un selector del tipo @media. Se puede indicar solo en caso que se necesite y si no se indica nada, afectará a todos los tipos de pantallas.
Dada la forma con la que se selecciona el archivo entre los distintos SOURCE se debe tener en cuenta que podría haber varias imágenes que el navegador podría representar, pero solo se indicará la primera que se adapte a las reglas en la mediaquery.
Sabiendo esto, podría ser interesante quitar el mediaquery de algún SOURCE, para que se use ese de manera predeterminada. En ese caso lo lógico sería colocar el SOURCE sin mediaquery al final del todo.
<picture>
<source media="(min-width: 900px)" srcset="grande.png">
<source media="(min-width: 550px)" srcset="media.png">
<source srcset="peque.png">
<img src="predeterminado.png">
</picture>
En el código anterior se usaría grande.png para pantallas de 900 píxeles en adelante. Se usaría media.png en pantallas de 550 píxeles y hasta 899 píxeles de anchura. Se usaría peque.png en todas las demás pantallas. Por último se usaría predeterminado.png en cualquier navegador que no sea capaz de interpretar el elemento PICTURE.
Sizes:
Este atributo nos ayudará a realizar una selección de la imagen apropiada de una manera distinta. Es un poco más sofisticado y por ello puede parecer un poco más complejo, pero en la práctica estamos delegando más al navegador la elección de la imagen que irá a utilizar, por lo que no debe causar problemas.
Hasta el momento al navegador le estamos indicando las imágenes que debe usar para cada rango de píxeles. Además sobre qué imágenes deben aplicarse para distintas densidades de píxeles. Ahora con el atriburo "sizes" podemos indicar la anchura de la imagen y dejar al navegador que escoja la imagen en función de varios archivos proporcionados. El navegador será el responsable de, atendiendo al tamaño de la ventana y la densidad de píxeles, escoger la mejor alternativa.
Este atributo se combina con el atributo de antes, "srcset" para indicar las distintas alternativas de archivos gráficos.
<picture>
<source media="(min-width: 600px)" sizes="65vw" srcset="peque.png 256w, media.png 456w, grande.png 856w, gigante.png 1280w">
<img src="media.png" sizes="65vw" srcset="peque.png 256w, media.png 456w, grande.png 856w, gigante.png 1280w">
</picture>
Para el código anterior. Anchuras de pantalla superiores a 600px aplica lo indicado en la etiqueta SOURCE y para pantallas menores se aplica lo indicado en la etiqueta IMG. Es un poco redundante, pero también podría ocurrir que un navegador no conozca PICTURE pero sí los atributos "sizes" y "srcset".
type:
Este atributo permite indicar el tipo de una imagen, de modo que el navegador pueda seleccionarlo si es que conoce ese formato de archivo.
Aplicar estilos CSS al elemento picture
Una duda que seguramente podremos tener es ¿cómo aplicar estilos CSS al elemento picture, ya que la etiqueta es picture y realmente hay como varias imágenes dentro. ¿Qué selector CSS utilizamos?
La respuesta no es nada compleja, ya que el estilo lo vamos a aplicar sobre el elemento IMG, como cualquier otra imagen HTML tradicional. Cualquier CSS actualmente aplicado sobre las imágenes, aplicará también al elemento picture.
Por ejemplo, para el siguiente HTML:
<div class="Panel">
<picture>
<source media="(min-width: 751px)" srcset="/images/foto@3x.jpg">
<source media="(min-width: 380px)" srcset="/image/foto@2x.jpg">
<img src="/images/foto.jpg" alt="Mi imagen responsive">
</picture>
</div>
Podríamos tener un CSS que aplique particularmente a esta etiqueta picture con el siguiente CSS:
.Panel {
img {
max-width: 100%;
}
}
Compatibilidad con el elemento picture
En cuanto a soporte de la etiqueta <picture>
tenemos muy buenas noticias, porque actualmente es excelente. Pero aunque no lo fuera debemos saber que gracias al fallback que se aplica con la etiqueta <img>
, no hay motivo para dejar de usarlo, ya que todos los navegadores usarán como mínimo la etiqueta IMG que siempre va a estar presente dentro del elemento picture.
En cualquier caso, este nuevo elemento está disponible ya en la mayoría de los navegadores. Solo falta compatibilidad con Internet Explorer y Opera Mini, lo que actualmente es mucho más que suficiente, ya que son dos navegadores abandonados.
Actualizado: El último navegador en aplicar soporte fue Safari para iOS, a partir de la versión 9.3 en iOS 13.
En la siguiente imagen de Caniuse podemos ver la tabla de soporte.
En definitiva el elemento <picture>
es perfectamente usable ya mismo. Además es recomendable porque los navegadores que lo interpreten gozarán de la posibilidad de tener imágenes adaptadas a resoluciones. Los que aun no lo implementen simplemente lo ignorarán, dejando toda la responsabilidad sobre la imagen indicada en la etiqueta <img>
de toda la vida.
No obstante, si queremos dar soporte para que algún navegador antiguo también pueda implementar imágenes responsive con el elemento picture, podemos cargar el correspondiente polyfill. Este proyecto llamado "Picturefill" contiene un script para que mediante Javascript se pueda dar soporte a PICTURE, así como los atribtos "srcset" y "sizes". Yo personalmente no veo muy necesario gastar tiempo y recursos Javascript para aplicar este polyfill, pero ahí os queda para los que lo necesitéis.
Actualizado: El polifill de Picturefill ya no se mantiene más por lo que hemos retirado el enlace.
Miguel Angel Alvarez
Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...