Carga diferida de imágenes a nivel del navegador para la Web

Navegadores compatibles

  • 77
  • 79
  • 75
  • 15.4

Puedes usar el atributo loading para cargar imágenes de forma diferida sin necesidad de escribir código personalizado de carga diferida o usar una biblioteca JavaScript separada. A continuación, se incluye una demostración de la función:

Las imágenes de carga diferida se cargan a medida que el usuario se desplaza por la página.

En esta página, se explican los detalles de la implementación de la carga diferida en el navegador.

¿Por qué usar la carga diferida a nivel del navegador?

Según el archivo HTTP, las imágenes son el tipo de recurso más solicitado para la mayoría de los sitios web y, por lo general, ocupan más ancho de banda que cualquier otro recurso. En el percentil 90, los sitios envían más de 5 MB de imágenes en computadoras de escritorio y dispositivos móviles.

Anteriormente, había dos formas de diferir la carga de imágenes fuera de pantalla:

Cualquiera de las dos opciones puede permitir que los desarrolladores incluyan un comportamiento de carga diferida, y muchos desarrolladores compilaron bibliotecas de terceros para proporcionar abstracciones que sean aún más fáciles de usar.

Sin embargo, con la carga diferida que el navegador admite directamente, no es necesario disponer de una biblioteca externa. La carga diferida a nivel del navegador también garantiza que la carga de imágenes funcione aunque el cliente inhabilite JavaScript. Sin embargo, ten en cuenta que la carga solo se aplaza cuando JavaScript está habilitado.

El atributo loading

Chrome carga las imágenes con diferentes prioridades según su ubicación en relación con el viewport del dispositivo. Las imágenes debajo del viewport se cargan con una prioridad más baja, pero aún se recuperan a medida que se carga la página.

Puedes usar el atributo loading para diferir por completo la carga de imágenes fuera de pantalla:

<img src="image.png" loading="lazy" alt="…" width="200" height="200">

Estos son los valores admitidos para el atributo loading:

  • lazy: Difiere la carga del recurso hasta que alcance una distancia calculada desde el viewport.
  • eager: Es el comportamiento de carga predeterminado del navegador, que es lo mismo que no incluir el atributo y significa que la imagen se carga independientemente de dónde se encuentre en la página. Este es el valor predeterminado, pero puede ser útil configurarlo de forma explícita si tus herramientas agregan automáticamente loading="lazy" cuando no hay un valor explícito, o si linter reclama si no está configurado de manera explícita.

Relación entre el atributo loading y la prioridad de recuperación

El valor eager es una instrucción para cargar la imagen como de costumbre, sin retrasar más la carga si la imagen está fuera de la pantalla. No carga la imagen más rápido que otra sin el atributo loading.

Si deseas aumentar la prioridad de recuperación de una imagen importante (por ejemplo, la imagen LCP), usa Prioridad de recuperación con fetchpriority="high".

Una imagen con loading="lazy" y fetchpriority="high" sigue retrasada mientras está fuera de la pantalla y, luego, se recupera con una prioridad alta cuando está casi dentro del viewport. Esta combinación no es realmente necesaria porque el navegador probablemente cargaría esa imagen con prioridad alta de todos modos.

Umbrales de distancia desde el viewport

Todas las imágenes que se pueden ver de inmediato sin tener que desplazarse se cargan normalmente. Las imágenes que se encuentran por debajo del viewport del dispositivo solo se recuperan cuando el usuario se desplaza cerca de ellas.

La implementación de la carga diferida de Chromium intenta garantizar que las imágenes fuera de pantalla se carguen lo suficientemente temprano como para que terminen de cargarse cuando el usuario se desplaza hacia ellas. Para ello, se recuperan mucho antes de que se vuelvan visibles en el viewport.

El umbral de distancia varía según los siguientes factores:

Puedes encontrar los valores predeterminados para los diferentes tipos de conexión efectivas en la fuente de Chromium. Puedes experimentar con estos diferentes umbrales mediante la regulación de la red en Herramientas para desarrolladores.

Mejoras en el ahorro de datos y los umbrales de distancia del viewport

En julio de 2020, Chrome realizó mejoras significativas para alinear los umbrales de la distancia de carga diferida de las imágenes desde el viewport y satisfacer mejor las expectativas de los desarrolladores.

En conexiones rápidas (4G), redujimos los umbrales de distancia del viewport de Chrome de 3000px a 1250px y, en conexiones más lentas (3G o inferiores), cambiamos el umbral de 4000px a 2500px. Con este cambio, se logran dos objetivos:

  • <img loading=lazy> se comporta de un modo más parecido a la experiencia que ofrecen las bibliotecas de carga diferida de JavaScript.
  • Los nuevos umbrales de distancia desde la ventana de visualización significan que las imágenes probablemente se habrán cargado cuando el usuario se desplace hasta ellas.

A continuación, encontrará una comparación entre los umbrales de la distancia del viewport anterior con los nuevos para una de nuestras demostraciones en una conexión rápida (4G):

Comparación entre los umbrales anteriores y los nuevos:

Los umbrales nuevos y mejorados para la carga diferida de imágenes reducen los umbrales de distancia desde el viewport para conexiones rápidas de 3,000 px a 1,250 px.
Comparación entre los umbrales más antiguos y nuevos que se usan para la carga diferida nativa.

y los nuevos umbrales en comparación con LazySizes (una popular biblioteca de carga diferida de JavaScript):

Los nuevos umbrales de distancia desde la ventana de visualización en Chrome que cargan 90 KB de imágenes en comparación con LazySizes que se cargan en 70 KB en las mismas condiciones de red
Comparación de los umbrales usados para la carga diferida en Chrome y LazySizes.

Cómo proporcionar los atributos de dimensiones de tus imágenes

Mientras el navegador carga una imagen, no conoce de inmediato sus dimensiones, a menos que se especifiquen explícitamente. A fin de permitir que el navegador reserve suficiente espacio en una página para las imágenes y evitar cambios de diseño molestos, recomendamos agregar los atributos width y height a todas las etiquetas <img>.

<img src="image.png" loading="lazy" alt="…" width="200" height="200">

Como alternativa, especifica sus valores directamente en un estilo intercalado:

<img src="image.png" loading="lazy" alt="…" style="height:200px; width:200px;">

La práctica recomendada de configurar las dimensiones se aplica a las etiquetas <img> independientemente de si realizas una carga diferida, pero esta puede hacer que sea más importante.

La carga diferida en Chromium se implementa de manera que las imágenes tengan más probabilidades de cargarse en cuanto sean visibles, pero existe la posibilidad de que no se carguen en el momento adecuado. Si eso sucede, no especificar width ni height en tus imágenes aumenta su impacto en el Cambio de diseño acumulado. Si no puedes especificar las dimensiones de las imágenes, una carga diferida puede ahorrar recursos de red, a riesgo de estos mayores cambios de diseño.

En la mayoría de los casos, las imágenes aún se cargan de forma diferida si no especificas dimensiones, pero hay algunos casos extremos que debes tener en cuenta. Si no se especifican width ni height, las dimensiones de la imagen se establecen de forma predeterminada en 0 × 0 píxeles. Si tienes una galería de imágenes, el navegador podría decidir que todas caben dentro del viewport al inicio, porque cada imagen no ocupa espacio y ninguna imagen se desplaza fuera de la pantalla. En este caso, el navegador decide cargar todo, lo que hace que la página se cargue más lento.

Para ver un ejemplo de cómo funciona loading con una gran cantidad de imágenes, consulta esta demostración.

También puedes realizar una carga diferida de imágenes que definiste con el elemento <picture>:

<picture>
  <source media="(min-width: 800px)" srcset="large.jpg 1x, larger.jpg 2x">
  <img src="photo.jpg" loading="lazy">
</picture>

Si bien el navegador decide qué imagen cargar desde cualquiera de los elementos <source>, solo debes agregar loading al elemento <img> de resguardo.

Siempre cargar con anticipación las imágenes visibles en el primer viewport

En el caso de las imágenes que son visibles cuando el usuario carga la página por primera vez y, en especial, para las imágenes LCP, usa la carga inmediata predeterminada del navegador para que estén disponibles de inmediato. Para obtener más información, consulta Efectos en el rendimiento de demasiada carga diferida.

Usa loading=lazy solo para imágenes fuera del viewport inicial. El navegador no puede hacer una carga diferida de una imagen hasta que sepa dónde debería estar en la página, lo que hace que se cargue más lento.

<!-- visible in the viewport -->
<img src="product-1.jpg" alt="..." width="200" height="200">
<img src="product-2.jpg" alt="..." width="200" height="200">
<img src="product-3.jpg" alt="..." width="200" height="200">

<!-- offscreen images -->
<img src="product-4.jpg" loading="lazy" alt="..." width="200" height="200">
<img src="product-5.jpg" loading="lazy" alt="..." width="200" height="200">
<img src="product-6.jpg" loading="lazy" alt="..." width="200" height="200">

Degradación correcta

Los navegadores que no admiten el atributo loading lo ignoran. No obtienen los beneficios de la carga diferida, pero no tiene un impacto negativo de incluirla.

Preguntas frecuentes

¿Puedo hacer una carga diferida de imágenes automáticamente en Chrome?

Anteriormente, Chromium realizaba una carga diferida de forma automática todas las imágenes que se ajustaban a aplazamientos si el modo lite estaba habilitado en Chrome para Android y no se proporcionaba el atributo loading o se establecía en loading="auto". Sin embargo, el modo lite y loading="auto" dejaron de estar disponibles, y no hay planes de proporcionar automáticamente carga diferida de imágenes en Chrome.

¿Puedo cambiar qué tan cerca debe estar una imagen del viewport antes de que se cargue?

Estos valores están codificados y no se pueden cambiar mediante la API. Sin embargo, podrían cambiar en el futuro a medida que los navegadores experimenten con diferentes variables y distancias límite.

¿Las imágenes de fondo de CSS pueden usar el atributo loading?

No, solo puedes usarlo con las etiquetas <img>.

El uso de loading="lazy" puede evitar que se carguen imágenes cuando no son visibles, pero están dentro de la distancia calculada. Es posible que estas imágenes estén detrás de un carrusel o que el CSS las oculte para ciertos tamaños de pantalla. Por ejemplo, Chrome, Safari y Firefox no cargan imágenes con el estilo display: none;, ya sea en el elemento de imagen o en un elemento superior. Sin embargo, otras técnicas de ocultamiento de imágenes, como el uso de diseño opacity:0, hacen que el navegador cargue la imagen de todas formas. Siempre prueba tu implementación de forma exhaustiva para asegurarte de que funcione según lo previsto.

Chrome 121 cambió el comportamiento de las imágenes de desplazamiento horizontal, como los carruseles. Estas ahora usan los mismos umbrales que el desplazamiento vertical. Esto significa que, para el caso de uso de carrusel, las imágenes se cargarán antes de que sean visibles en el viewport. Esto significa que es menos probable que la carga de la imagen sea visible para el usuario, pero a costa de una mayor cantidad de descargas. Utiliza la demostración de la carga diferida horizontal para comparar el comportamiento en Chrome con el de Safari y Firefox.

¿Qué sucede si ya uso una biblioteca de terceros o una secuencia de comandos para cargar imágenes de forma diferida?

Gracias a la compatibilidad total con la carga diferida integrada en los navegadores modernos, es probable que no necesites una biblioteca o secuencia de comandos de terceros para cargar imágenes de forma diferida.

Un motivo para seguir usando una biblioteca de terceros junto con loading="lazy" es proporcionar un polyfill para los navegadores que no admiten el atributo o para tener más control sobre cuándo se activa la carga diferida.

¿Cómo controlo los navegadores que no admiten la carga diferida? {browsers-dont-support}

Crea un polyfill o usa una biblioteca de terceros para cargar imágenes de forma diferida en tu sitio. Puedes usar la propiedad loading para detectar si un navegador admite la función:

if ('loading' in HTMLImageElement.prototype) {
  // supported in browser
} else {
  // fetch polyfill/third-party library
}

Por ejemplo, lazysizes es una biblioteca popular de carga diferida de JavaScript. Es posible detectar compatibilidad con el atributo loading para cargar lazysizes como una biblioteca de resguardo solo cuando loading no sea compatible. Esto funciona de la siguiente manera:

  • Reemplaza <img src> por <img data-src> para evitar una carga inmediata en navegadores no compatibles. Si se admite el atributo loading, intercambia data-src por src.
  • Si no se admite loading, carga un resguardo de tamaños diferidos y, luego, inícialo con la clase lazyload para indicar qué imágenes se deben cargar de forma diferida:
<!-- Let's load this in-viewport image normally -->
<img src="hero.jpg" alt="…">

<!-- Let's lazy-load the rest of these images -->
<img data-src="unicorn.jpg" alt="…" loading="lazy" class="lazyload">
<img data-src="cats.jpg" alt="…" loading="lazy" class="lazyload">
<img data-src="dogs.jpg" alt="…" loading="lazy" class="lazyload">

<script>
  if ('loading' in HTMLImageElement.prototype) {
    const images = document.querySelectorAll('img[loading="lazy"]');
    images.forEach(img => {
      img.src = img.dataset.src;
    });
  } else {
    // Dynamically import the LazySizes library
    const script = document.createElement('script');
    script.src =
      'https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.1.2/lazysizes.min.js';
    document.body.appendChild(script);
  }
</script>

Aquí hay una demostración de este patrón. Pruébalo en un navegador anterior para ver el resguardo en acción.

¿Los navegadores también admiten la carga diferida de iframes?

Navegadores compatibles

  • 77
  • 79
  • 121
  • 16.4

<iframe loading=lazy> también se estandarizó. Esto te permite realizar una carga diferida de iframes con el atributo loading. Para obtener más información, consulta Es hora de realizar una carga diferida de iframes fuera de pantalla.

¿De qué manera la carga diferida a nivel del navegador afecta los anuncios de una página web?

Son todos los anuncios que se muestran al usuario como imágenes o iframes, como cualquier otra imagen o iframe.

¿Cómo se manejan las imágenes cuando se imprime una página web?

Todas las imágenes y los iframes se cargan inmediatamente cuando se imprime la página. Consulta el error #875403 para obtener más detalles.

¿Lighthouse reconoce la carga diferida a nivel del navegador?

Lighthouse 6.0 y las versiones posteriores consideran los enfoques para la carga diferida de imágenes fuera de pantalla que pueden usar diferentes umbrales, lo que les permite pasar la auditoría de Aplazar imágenes fuera de pantalla.

Imágenes de carga diferida para mejorar el rendimiento

La compatibilidad del navegador con la carga diferida de imágenes puede facilitar mucho la mejora del rendimiento de tus páginas.

¿Notas algún comportamiento inusual cuando está habilitada esta función en Chrome? Informa un error.