Rendimiento de las imágenes

Las imágenes suelen ser el recurso más pesado y prevalente de la Web. Como resultado, optimizar las imágenes puede mejorar significativamente el rendimiento en tu sitio web. En la mayoría de los casos, optimizar las imágenes implica reducir el tiempo de red mediante el envío de menos bytes, pero también puedes optimizar la cantidad de bytes que se envían al usuario mediante la entrega de imágenes con un tamaño adecuado para el dispositivo del usuario.

Se pueden agregar imágenes a una página con los elementos <img> o <picture>, o con la propiedad background-image de CSS.

Tamaño de la imagen

La primera optimización que puedes realizar cuando se trata de usar recursos de imagen es mostrar la imagen en el tamaño correcto; en este caso, el término tamaño se refiere a las dimensiones de una imagen. Sin considerar otras variables, una imagen que se muestra en un contenedor de 500 x 500 píxeles tendría un tamaño óptimo de 500 x 500 píxeles. Por ejemplo, usar una imagen cuadrada de 1,000 píxeles significa que la imagen es dos veces más grande según sea necesario.

Sin embargo, hay muchas variables involucradas en la elección del tamaño de imagen adecuado, lo que dificulta la tarea de elegir el tamaño de imagen adecuado en cada caso. En 2010, cuando se lanzó el iPhone 4, la resolución de pantalla (640 x 960) era el doble que la del iPhone 3 (320 x 480). Sin embargo, el tamaño físico de la pantalla del iPhone 4 se mantuvo casi igual al del iPhone 3.

Mostrar todo con una resolución más alta habría hecho que el texto y las imágenes fueran mucho más pequeños (la mitad de su tamaño anterior para ser exactos). En cambio, 1 píxel se convirtió en 2 píxeles del dispositivo. Esto se denomina relación de píxeles del dispositivo (DPR). El iPhone 4, y muchos modelos de iPhone lanzados después, tenían una DPR de 2.

En el ejemplo anterior, si el dispositivo tiene una DPR de 2 y la imagen se muestra en un contenedor de 500 píxeles por 500 píxeles, el tamaño óptimo ahora será una imagen cuadrada de 1,000 píxeles (denominada tamaño intrínseco). Del mismo modo, si el dispositivo tiene una DPR de 3, el tamaño óptimo sería una imagen cuadrada de 1,500 píxeles.

srcset

El elemento <img> admite el atributo srcset, que te permite especificar una lista de posibles fuentes de imágenes que el navegador puede usar. Cada fuente de imagen especificada debe incluir la URL de la imagen y un descriptor de ancho o de densidad de píxeles.

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>

En el fragmento HTML anterior, se usa el descriptor de densidad de píxeles para sugerir al navegador que use image-500.png en dispositivos con una DPR de 1, image-1000.jpg en dispositivos con una DPR de 2 y image-1500.jpg en dispositivos con una DPR de 3.

Si bien todo esto puede parecer simple, la DPR de una pantalla no es la única consideración para elegir la imagen óptima para una página determinada. El diseño de la página es otra consideración más.

sizes

La solución anterior solo funciona si muestras la imagen con el mismo tamaño de píxeles CSS en todos los viewports. En muchos casos, el diseño de una página (y el tamaño del contenedor con ella) cambia según el dispositivo del usuario.

El atributo sizes te permite especificar un conjunto de tamaños de fuente, en el que cada tamaño consta de una condición de contenido multimedia y un valor. El atributo sizes describe el tamaño de visualización previsto de la imagen en píxeles CSS. Cuando se combina con los descriptores de ancho srcset, el navegador puede elegir qué fuente de imágenes es mejor para el dispositivo del usuario.

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"
  sizes="(min-width: 768px) 500px, 100vw"
>

En el fragmento HTML anterior, el atributo srcset especifica una lista de opciones de imagen que el navegador puede elegir, separadas por comas. Cada candidato de la lista consiste en la URL de la imagen, seguida de una sintaxis que denota el ancho intrínseco de la imagen. El tamaño intrínseco de una imagen son sus dimensiones. Por ejemplo, un descriptor de 1000w indica que el ancho intrínseco de la imagen es de 1,000 píxeles de ancho.

Con esta información, el navegador evalúa la condición del contenido multimedia en el atributo sizes y, en este caso, se le indica que, si el ancho del viewport del dispositivo supera los 768 píxeles, la imagen se muestra con un ancho de 500 píxeles. En dispositivos más pequeños, la imagen se muestra en 100vw o en el ancho completo del viewport.

Luego, el navegador puede combinar esta información con la lista de fuentes de imágenes srcset para encontrar la imagen óptima. Por ejemplo, si el usuario usa un dispositivo móvil con un ancho de pantalla de 320 píxeles con una DPR de 3, la imagen se muestra en 320 CSS pixels x 3 DPR = 960 device pixels. En este ejemplo, la imagen de tamaño más cercano sería image-1000.jpg, que tiene un ancho intrínseco de 1,000 píxeles (1000w).

Formatos de archivo

Los navegadores admiten varios formatos de archivos de imagen diferentes. Los formatos de imagen modernos, como WebP y AVIF, pueden comprimir mejor las imágenes que PNG o JPEG, lo que reduce el tamaño del archivo de imagen y, por lo tanto, tarda menos tiempo en descargarse. Cuando entregas imágenes en formatos modernos, puedes reducir el tiempo de carga de un recurso, lo que puede generar un Procesamiento de imagen con contenido más grande (LCP) más bajo.

WebP es un formato gran compatibilidad que funciona en todos los navegadores modernos. WebP suele tener una mejor compresión que JPEG, PNG o GIF, y ofrece una compresión con pérdida y la sin pérdida. WebP también admite la transparencia de canal alfa incluso cuando se utiliza la compresión con pérdida, una función que el códec JPEG no ofrece.

AVIF es un formato de imagen más nuevo y, si bien no es tan compatible como WebP, goza de una compatibilidad razonablemente aceptable con todos los navegadores. AVIF admite compresión con y sin pérdida, y las pruebas mostraron ahorros superiores al 50% en comparación con JPEG en algunos casos. AVIF también ofrece funciones de Gamut amplio de colores (WCG) y Alto rango dinámico (HDR).

Compresión

En lo que respecta a las imágenes, hay dos tipos de compresión:

  1. Compresión con pérdida
  2. Compresión sin pérdida

La compresión con pérdida funciona reduciendo la precisión de la imagen mediante la cuantización. Además, la información adicional del color podría descartarse con el submuestreo de croma. La compresión con pérdida es más eficaz en imágenes de alta densidad con mucho ruido y colores, por lo general, fotos o imágenes con contenido similar. Esto se debe a que es mucho menos probable que los artefactos producidos por la compresión con pérdida se noten en imágenes tan detalladas. Sin embargo, la compresión con pérdida puede ser menos eficaz con imágenes que contienen bordes nítidos, como el diseño de líneas, detalles austeros similares o texto. La compresión con pérdida se puede aplicar a imágenes JPEG, WebP y AVIF.

La compresión sin pérdida reduce el tamaño del archivo mediante la compresión de una imagen sin pérdida de datos. La compresión sin pérdida describe un píxel en función de la diferencia de los píxeles cercanos. La compresión sin pérdida se utiliza para los formatos de imagen GIF, PNG, WebP y AVIF.

Puedes comprimir tus imágenes con Squoosh, ImageOptim o con un servicio de optimización de imágenes. Durante la compresión, no hay una configuración universal adecuada para todos los casos. El enfoque recomendado sería experimentar con diferentes niveles de compresión hasta encontrar un buen compromiso entre la calidad de la imagen y el tamaño del archivo. Algunos servicios avanzados de optimización de imágenes pueden hacerlo por ti automáticamente, pero es posible que no sean viables desde el punto de vista financiero para todos los usuarios.

El elemento <picture>

El elemento <picture> te brinda una mayor flexibilidad cuando especificas varias opciones de imágenes:

<picture>
  <source type="image/avif" srcset="image.avif">
  <source type="image/webp" srcset="image.webp">
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image.jpg"
  >
</picture>

Cuando usas elementos <source> dentro del elemento <picture>, puedes agregar compatibilidad con imágenes AVIF y WebP, pero puedes recurrir a formatos de imagen heredados más compatibles si el navegador no admite formatos modernos. Con este enfoque, el navegador selecciona el primer elemento <source> especificado que coincide. Si puede renderizar la imagen en ese formato, la usará. De lo contrario, el navegador pasa al siguiente elemento <source> especificado. En el fragmento HTML anterior, el formato AVIF tiene prioridad sobre el formato WebP y recurre al formato JPEG si no se admiten AVIF ni WebP.

Un elemento <picture> requiere un elemento <img> anidado dentro de él. Los atributos alt, width y height se definen en <img> y se usan sin importar qué <source> se seleccione.

El elemento <source> también admite los atributos media, srcset y sizes. Al igual que con el ejemplo anterior de <img>, estos le indican al navegador qué imagen seleccionar en diferentes viewports.

<picture>
  <source
    media="(min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

El atributo media toma una condición de contenido multimedia. En el ejemplo anterior, se usa la DPR del dispositivo como condición de contenido multimedia. Cualquier dispositivo con una DPR mayor o igual que 1.5 usaría el primer elemento <source>. El elemento <source> le indica al navegador que, en dispositivos con un viewport de más de 768 píxeles, la imagen candidata seleccionada se muestra con 500 píxeles de ancho. En dispositivos más pequeños, ocupa todo el ancho de la viewport. Si combinas los atributos media y srcset, puedes tener un control más preciso sobre qué imagen usar.

Esto se ilustra en la siguiente tabla, en la que se evalúan varios anchos de viewports y proporciones de píxeles del dispositivo:

Ancho de la vista del puerto (píxeles) 1 DPR DPR 1.5 DPR 2 DPR 3
320 500.jpg 500.jpg 500.jpg 1000.jpg
480 500.jpg 500.jpg 1000.jpg 1500.jpg
560 500.jpg 1000.jpg 1000.jpg 1500.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

Los dispositivos con una DPR de 1 descargan la imagen image-500.jpg, incluidos la mayoría de los usuarios de computadoras de escritorio, que ven la imagen en un tamaño extrínico de 500 píxeles de ancho. Por otro lado, los usuarios de dispositivos móviles con una DPR de 3 descargan un image-1500.jpg potencialmente más grande, la misma imagen que se usa en dispositivos de escritorio con una DPR de 3.

<picture>
  <source
    media="(min-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <source
    media="(max-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

En este ejemplo, se ajusta el elemento <picture> para incluir un elemento <source> adicional a fin de usar diferentes imágenes en dispositivos anchos con una DPR alta:

Ancho de la vista del puerto (píxeles) 1 DPR DPR 1.5 DPR 2 DPR 3
320 500.jpg 500.jpg 500.jpg 1000-sm.jpg
480 500.jpg 500.jpg 1000-sm.jpg 1500-sm.jpg
560 500.jpg 1000-sm.jpg 1000-sm.jpg 1500-sm.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

Con esta consulta adicional, puedes ver que image-1000-sm.jpg y image-1500-sm.jpg se muestran en viewports pequeños. Esta información adicional te permite comprimir aún más las imágenes, ya que los artefactos de compresión no son muy visibles en ese tamaño y densidad, y no comprometen la calidad de la imagen en los dispositivos de escritorio.

Como alternativa, ajusta los atributos srcset y media para evitar entregar imágenes grandes en viewports pequeños:

<picture>
  <source
    media="(min-width: 560px)"
    srcset="/image-500.jpg, /image-1000.jpg 2x, /image-1500.jpg 3x"
  >
  <source
    media="(max-width: 560px)"
    srcset="/image-500.jpg 1x, /image-1000.jpg 2x"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

En el fragmento HTML anterior, se quitaron los descriptores de ancho y se reemplazaron por los descriptores de proporción de píxeles del dispositivo. Las imágenes que se entregan en un dispositivo móvil se limitan a /image-500.jpg o /image-1000.jpg, incluso en dispositivos con una DPR de 3.

Cómo gestionar la complejidad

Cuando trabajes con imágenes responsivas, encontrarás muchos formatos y variaciones de tamaño diferentes para cada imagen. En el ejemplo anterior, se usan variaciones para cada tamaño, pero se excluyen AVIF y WebP. ¿Cuántas variantes deberías tener? Como muchos problemas de ingeniería, la respuesta tiende a ser "depende".

Si bien puede ser tentador tener tantas variaciones para ofrecer el mejor ajuste, cada variante de imagen adicional tiene un costo y hace que el uso de la caché del navegador sea menos eficiente. Con una sola variante, cada usuario recibe la misma imagen, por lo que se puede almacenar en caché de manera muy eficiente.

Por otro lado, si hay muchas variaciones, cada variante requiere otra entrada de caché. Los costos del servidor pueden aumentar y degradar el rendimiento si la entrada de caché de la variante venció y la imagen debe recuperarse desde el servidor de origen.

Aparte de esto, el tamaño de tu documento HTML aumenta con cada variación. Podrías enviar varios kilobytes de HTML para cada imagen.

Entrega imágenes según el encabezado de la solicitud Accept

El encabezado de la solicitud HTTP Accept informa al servidor qué tipos de contenido comprende el navegador del usuario. El servidor puede usar esta información para entregar el formato de imagen óptimo sin agregar bytes adicionales a tus respuestas HTML.

if (request.headers.accept) {
  if (request.headers.accept.includes('image/avif')) {
    return reply.from('image.avif');
  } else if (request.headers.accept.includes('image/webp')) {
    return reply.from('image.webp');
  }
}

return reply.from('image.jpg');

El fragmento HTML anterior es una versión simplificada del código que puedes agregar al backend de JavaScript de tu servidor para elegir y publicar el formato de imagen óptimo. Si el encabezado Accept de la solicitud incluye image/avif, se entrega la imagen AVIF. De lo contrario, si el encabezado Accept incluye image/webp, se entrega la imagen WebP. Si ninguna de estas condiciones es verdadera, se entrega la imagen JPEG.

Puedes modificar las respuestas según el contenido del encabezado de la solicitud Accept en casi todos los tipos de servidor web. Por ejemplo, puedes volver a escribir las solicitudes de imágenes en servidores Apache basadas en el encabezado Accept mediante mod_rewrite.

Este comportamiento se parece a los que encontrarías en una red de distribución de contenidos de imágenes (CDN). Las CDN de imágenes son soluciones excelentes para optimizar imágenes y enviar el formato óptimo según el dispositivo y el navegador del usuario.

La clave es encontrar un equilibrio, generar una cantidad razonable de opciones de imágenes y medir el impacto en la experiencia del usuario. Las diferentes imágenes pueden dar distintos resultados, y las optimizaciones que se aplican a cada una dependen de su tamaño dentro de la página y de los dispositivos que usan los usuarios. Por ejemplo, una imagen principal de ancho completo puede requerir más variantes que las imágenes en miniatura en una página de ficha de producto de comercio electrónico.

Carga diferida

Puedes indicarle al navegador que cargue de forma diferida las imágenes cuando aparecen en el viewport mediante el atributo loading. Un valor de atributo de lazy le indica al navegador que no descargue la imagen hasta que esté en el viewport (o cerca de él). Esto ahorra ancho de banda, lo que permite que el navegador priorice los recursos que necesita para renderizar el contenido crítico que ya está en el viewport.

decoding

El atributo decoding le indica al navegador cómo debe decodificar la imagen. Un valor de async indica al navegador que la imagen se puede decodificar de forma asíncrona, lo que posiblemente mejora el tiempo de renderización de otro contenido. Un valor de sync le indica al navegador que la imagen debe presentarse al mismo tiempo que otro contenido. El valor predeterminado de auto permite que el navegador decida lo que es mejor para el usuario.

Demostraciones de imágenes

Pon a prueba tus conocimientos

¿Qué formatos de imagen admiten la compresión sin pérdida?

GIF.
Correcto.
JPEG.
Vuelve a intentarlo.
PNG.
Correcto.
WebP
Correcto.
AVIF.
Correcto.

¿Qué formatos de imagen admiten la compresión con pérdida?

GIF.
Vuelve a intentarlo. Si bien el formato GIF solo admite una paleta limitada de 256 colores, se debe realizar la codificación con pérdida antes de convertirlo en GIF.
JPEG.
Correcto.
PNG.
Vuelve a intentarlo.
WebP
Correcto.
AVIF.
Correcto.

¿Qué le informa al navegador el descriptor de ancho (por ejemplo, 1000w) sobre una candidata de imagen especificada en un atributo srcset?

El ancho extrínico de la imagen, es decir, las dimensiones de la imagen en el diseño después de aplicar los estilos a la página
Vuelve a intentarlo.
Es el ancho intrínseco de la imagen, es decir, las dimensiones de la propia imagen.
Correcto.

¿Qué le informa el atributo sizes al navegador sobre un elemento <img> al que se aplica?

Lógica que expresa qué candidato especificado en el srcset de un elemento <img> se debe cargar, según las dimensiones del viewport actual del usuario.
Correcto.
Es el ancho intrínseco de la imagen que se cargará desde el atributo srcset del elemento <img>.
Vuelve a intentarlo.

A continuación: Rendimiento del video

Si bien las imágenes pueden ser el tipo de medio más frecuente que se usa en la Web, están lejos de ser el único que debes tener en cuenta cuando se trata del rendimiento. Los videos son otro tipo de contenido multimedia que se usa con frecuencia en la Web y tienen sus propias consideraciones de rendimiento. En el siguiente módulo de este curso, explorarás algunas técnicas para optimizar videos y cargarlos de manera eficiente.