Las pantallas con alta densidad de píxeles se están convirtiendo rápidamente en la norma. Los creadores de contenido deben adaptarse a este hecho. Esta es una breve guía sobre cómo entregar imágenes de alta calidad en la Web en la actualidad, sin polyfills, JavaScript, hacks de CSS y funciones del navegador que aún no se implementan. En una palabra: sin cambios drásticos en tu flujo de trabajo.
En la actualidad, existen muchas propuestas de imágenes responsivas y muchas de ellas implican cambios significativos para el desarrollador web. El atributo <img>
del segmento estándar srcset
es difícil de implementar, en especial debido a la complejidad de la selección adicional basada en viewport de srcset
:
banner-HD.jpeg 2x, banner-phone.jpeg 100w, banner-phone-HD.jpeg 100w 2x
Aunque la propiedad CSS image-set
solo usa devicePixelRatio
para decidir qué imagen cargar, de todos modos, obliga a los desarrolladores a escribir mucho código de marcado adicional para cada imagen.
Otras propuestas, como el elemento <picture>
, son aún más detalladas.
Además, no son un segmento estándar, por lo que su disponibilidad omnipresente es mucho mayor que el atributo srcset. JavaScript y las soluciones del servidor son la única otra alternativa, pero estos enfoques tienen sus propias desventajas, como se explica en otros artículos.
En este artículo, se explican varios usos de las imágenes que se encuentran comúnmente en la Web y se proponen soluciones simples que funcionan en pantallas con alta densidad de píxeles, además de otras comunes. A los efectos de esta discusión, cualquier dispositivo que informe un window.devicePixelRatio
superior a 1 se puede considerar de alta densidad de píxeles, ya que eso significa que los píxeles CSS no son iguales a los píxeles del dispositivo y que las imágenes se están ampliando.
Aquí encontrarás un resumen:
- Si es posible, usa CSS o SVG en lugar de imágenes rasterizadas.
- Usa imágenes optimizadas para pantallas de alta densidad de forma predeterminada.
- Usa archivos PNG para dibujos simples y pixel art (p. ej., logotipos).
- Usa archivos JPEG comprimidos para imágenes con una variedad de colores (p. ej., fotos).
- Siempre establece tamaños explícitos (con CSS o HTML) en todos los elementos de imagen.
Dibujos simples y pixel art
A menudo, las imágenes pequeñas se pueden evitar por completo usando funciones de CSS o SVG.
No es necesario usar imágenes para las esquinas redondeadas, por ejemplo, ya que la propiedad CSS border-radius
es ampliamente compatible. Del mismo modo, las fuentes personalizadas son ampliamente compatibles, por lo que no se recomienda usar texto con imágenes.
Sin embargo, en algunos casos, como los logotipos, una imagen puede ser la única forma de avanzar. Por ejemplo, este logotipo de Chrome tiene un tamaño natural de 256 x 256. En una pantalla Retina, puedes ver la superposición de líneas en diagonales y curvas, que se ve de manera irregular y mal definida, en especial cuando se compara con un texto renderizado de forma nítida:
Dimensiones naturales: 256x256px
, tamaño del recurso: 31 kB
, formato: PNG
¿Te convence? Bien. Ahora, usemos una imagen de alta densidad. Es posible que te tiente ahorrar espacio almacenando tu logotipo como JPEG, pero esta no es una buena idea, ya que guardar logotipos y otros elementos gráficos en un formato con pérdida tiende a generar artefactos. En este caso, exageré el problema usando una compresión muy alta, pero observa las bandas en los gradientes, las manchas en los fondos blancos y las líneas desordenadas:
Dimensiones naturales: 512x512px
, tamaño del recurso: 13 kB
, formato: JPEG
Lo que se debe hacer con imágenes relativamente pequeñas es usar archivos PNG de tamaño 2x. Ten en cuenta que la diferencia de tamaño entre un PNG de 1x y un PNG de 2x es generalmente bastante alta (52 KB en este caso). Sin embargo, en el caso de un logotipo, es el rostro de tu sitio web y lo primero que verán los visitantes. Si escatimas demasiado en la calidad a cambio del tamaño, también será lo último que verán tus visitantes.
Este es el logotipo de Chrome en todo su esplendor, con el tamaño reducido a la mitad de sus dimensiones naturales para 2 pantallas:
Dimensiones naturales: 512x512px
, tamaño del recurso: 83 kB
, formato: PNG
El lenguaje de marcado para realizar la renderización anterior es el siguiente:
<img src="chrome2x.png" style="width: 256px; height: 256px;"/>
Ten en cuenta que especifiqué un ancho y una altura para la imagen. Esto es necesario porque el tamaño natural de la imagen es de 512 px. También es bueno para el rendimiento porque el motor de renderización tiene una buena comprensión del tamaño del elemento y no necesitará trabajar demasiado para calcularlo.
Una posible optimización que podría funcionar es reducir el PNG de 24 bits a uno de 8 bits con paleta. Esto funciona para imágenes con una pequeña cantidad de colores, incluido el logotipo de Chrome. Para realizar esta optimización, puedes usar una herramienta como http://pngquant.org/. Puedes ver algunas bandas aquí, pero este archivo solo pesa 13 KB, lo que equivale a un ahorro de tamaño de 6 veces en comparación con el PNG original de 512 x 512.
Dimensiones naturales: 512x512px
, tamaño del recurso: 13 kB
, formato: PNG,
8-bit palette
Imágenes con una variedad de colores
Escribí un artículo de HTML5Rocks que encuesta varias técnicas de imagen responsiva y, luego, investigué sobre la compresión de imágenes 1x y 2x JPEG, y la comparación de los tamaños resultantes y la calidad visual. A continuación, se muestra una de esas tarjetas del artículo anterior:
Etiqueté las imágenes con su nivel de compresión (indicado por la calidad JPEG), su tamaño (en bytes) y mi opinión subjetiva sobre su fidelidad visual comparativa (clasificada por números). Lo interesante aquí es que la imagen 2 veces más comprimida (etiquetada como 3) es más pequeña en tamaño y se ve mejor que la imagen sin comprimir (etiquetada como 4). En otras palabras, entre las imágenes 4 y 3, logramos mejorar la calidad de la imagen duplicando cada dimensión, aumentando significativamente la compresión y, al mismo tiempo, reduciendo el tamaño en 2 KB.
Compresión, dimensiones y calidad visual
Quería obtener más información sobre las compensaciones entre el nivel de compresión, las dimensiones de la imagen, la calidad visual y el tamaño de la imagen. Realicé un estudio con la siguiente hipótesis basado en el estudio anterior:
Hipótesis
Con una compresión suficiente, una imagen de 2x tendrá un aspecto equivalente a la misma imagen en un tamaño de 1x en alguna otra compresión (inferior). Sin embargo, en este caso, la imagen 2x altamente comprimida será más pequeña que la imagen 1x.
Proceso
- Dada una imagen de 2x, genera la de 1x.
- Comprime ambas imágenes en varios niveles.
- Crea una página de prueba que muestre ambos conjuntos de imágenes en paralelo.
- Busca el lugar en los dos conjuntos donde las imágenes son equivalentes.
- Ten en cuenta los tamaños de imagen y los niveles de compresión equivalentes.
- Pruébala en una pantalla 1x y 2x.
Compilé una app de comparación de imágenes en paralelo similar a la vista de comparación de Lightroom. La intención es mostrar imágenes de 1x y 2x en paralelo, pero también permitirte hacer zoom en cualquier sección de la imagen para obtener más detalles. También puedes seleccionar entre los formatos JPEG y WebP, y cambiar la calidad de compresión para ver las comparaciones de tamaño de archivo y calidad de imagen. La idea es ajustar la configuración en varias imágenes, averiguar qué relación entre calidad de compresión, escalamiento y formato en comparación con la calidad de la imagen te resulta más conveniente y usar esa configuración para todas tus imágenes.
La herramienta en sí está disponible para que la uses. Para acercar la imagen, selecciona una subárea.
Análisis
Antes que nada, debo decir que la calidad de la imagen es subjetiva. Además, es probable que tu caso de uso en particular dicte dónde se encuentran tus prioridades en el espectro de fidelidad visual frente al espectro de tamaño de archivo. Además, los diferentes tipos de funciones de imagen reaccionan de manera diferente a la escala y la calidad de compresión, por lo que es posible que una solución única no funcione aquí. El objetivo de la herramienta es ayudarte a desarrollar una intuición sobre las compresiones, escalas y formatos de calidad de imagen.
Después de jugar con el zoom de imágenes, rápidamente me hicieron evidentes algunas cosas. En primer lugar, prefiero las imágenes quality=30 dpr=2x
a las quality=90
dpr=1x
por el aumento en la cantidad de detalles. Estas imágenes también son comparables en tamaño de archivo (en el caso plano, la imagen 2x comprimida es de 76 kB, mientras que la imagen 1x sin comprimir es de 80 kB).
Las excepciones a esta regla son las imágenes con gradientes muy comprimidas (quality<30
). Estos tienden a tener bandas de color, lo que es igual de malo, independientemente de la escala de la imagen. Las muestras de aves y autos que se encuentran en la
herramienta son ejemplos de esto.
Las imágenes WebP se ven mucho más limpias que JPEG, en especial a niveles de compresión bajos. Parece que estas bandas de color son mucho menos problemáticas. Por último, las imágenes WebP son mucho más compactas.
Advertencias y aleta
Lograr que las imágenes se vean bien en pantallas de alta densidad es solo la mitad de los problemas relacionados con las imágenes que causa una gran variación en las pantallas. En algunos casos, es posible que desees entregar imágenes completamente diferentes según el tamaño del viewport. Por ejemplo, el retrato de Obama podría ser apropiado para una pantalla del tamaño de un teléfono, pero el soporte frente a él y la bandera detrás de él, y algunos podrían ser más adecuados para la pantalla de una laptop.
Evité deliberadamente este tema de “dirección de arte” para enfocarme solo en las imágenes de alta DPI. Este problema se puede resolver con varios enfoques diferentes: usar consultas de medios e imágenes de fondo, a través de JavaScript, a través de algunas funciones nuevas, como image-set
, o en el servidor. Este tema se trata en Imágenes con valores altos de DPI para densidades de píxeles variables.
Me despido con algunos problemas pendientes:
- Efectos de la alta compresión en el rendimiento ¿Cuáles son las penalizaciones de decodificar imágenes muy comprimidas?
- ¿Cuáles son las penalizaciones de rendimiento por tener que reducir el tamaño de la imagen cuando se carga una imagen de 2x en una pantalla de 1x?
En resumen, opta por CSS y SVG en lugar de usar imágenes de trama. Si las imágenes de trama son estrictamente necesarias, usa PNG para las imágenes con paletas limitadas y muchos colores sólidos, y usa JPEG para las imágenes con muchos colores y gradientes. Lo mejor de este enfoque es que tu marcado no cambia prácticamente. Lo único que debe hacer el desarrollador web es generar el doble de recursos y ajustar el tamaño de las imágenes correctamente en el DOM.
Para obtener más información, consulta el artículo de Scott Jehl sobre un tema similar. Que tus imágenes se vean nítidas y que el uso de datos móviles sea bajo.