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

Browser Support

  • Chrome: 77.
  • Edge: 79.
  • Firefox: 75.
  • Safari: 15.4.

Puedes usar el atributo loading para cargar imágenes de forma diferida sin necesidad de escribir código personalizado de carga diferida ni usar una biblioteca de JavaScript independiente. A continuación, se muestra 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 HTTP Archive, las imágenes son el tipo de recurso más solicitado en la mayoría de los sitios web y, por lo general, consumen 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 y dispositivos móviles.

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

Cualquiera de las opciones permite a los desarrolladores incluir el comportamiento de carga diferida, y muchos desarrolladores crearon bibliotecas de terceros para proporcionar abstracciones que son aún más fáciles de usar.

Sin embargo, con la carga diferida compatible directamente con el navegador, no se necesita una biblioteca externa. La carga diferida a nivel del navegador también garantiza que la carga de imágenes siga funcionando incluso si el cliente inhabilita 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 que se encuentran debajo del viewport se cargan con una prioridad más baja, pero se recuperan a medida que se carga la página.

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

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

Estos son los valores admitidos para el atributo loading:

  • lazy: Aplaza la carga del recurso hasta que alcance una distancia calculada desde el viewport.
  • eager: Es el comportamiento de carga predeterminado del navegador, que es el 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 establecerlo de forma explícita si tus herramientas agregan automáticamente loading="lazy" cuando no hay un valor explícito o si tu verificador de código muestra un error si no se establece de forma 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 de forma habitual, sin retrasar más la carga si la imagen está fuera de la pantalla. No carga la imagen más rápido que otra imagen que no tiene un atributo loading.

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

Una imagen con loading="lazy" y fetchpriority="high" se retrasa mientras está fuera de la pantalla y, luego, se recupera con una prioridad alta cuando está casi dentro de la ventana gráfica. Esta combinación no es realmente necesaria porque es probable que el navegador cargue esa imagen con alta prioridad de todos modos.

Umbrales de distancia desde el viewport

Todas las imágenes que se pueden ver de inmediato sin desplazarse se cargan normalmente. Las imágenes que se encuentran muy por debajo de la ventana gráfica 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 con la suficiente anticipación para que terminen de cargarse cuando el usuario se desplace hasta ellas. Para ello, las recupera 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 efectivos en la fuente de Chromium. Puedes experimentar con estos diferentes umbrales limitando la red en las Herramientas para desarrolladores.

Se mejoraron los umbrales de ahorro de datos y de distancia desde el viewport.

En julio de 2020, Chrome realizó mejoras significativas para alinear los umbrales de distancia desde la ventana gráfica de la carga diferida de imágenes 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 inferior), cambiamos el umbral de 4000px a 2500px. Este cambio logra dos objetivos:

  • <img loading=lazy> se comporta de manera más similar a la experiencia que ofrecen las bibliotecas de carga diferida de JavaScript.
  • Los nuevos umbrales de distancia desde el viewport aún significan que es probable que las imágenes se hayan cargado cuando un usuario se desplace hasta ellas.

A continuación, puedes ver una comparación entre los umbrales de distancia del viewport antiguos y los nuevos para una de nuestras demostraciones en una conexión rápida (4G):

Se mejoraron los umbrales para la carga diferida de imágenes, lo que redujo los umbrales de distancia desde la ventana gráfica para las conexiones rápidas de 3,000 px a 1,250 px.
Comparación de los límites anteriores y más recientes que se usan para la carga diferida a nivel del navegador.

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

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

Asigna atributos de dimensión a tus imágenes

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

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

Como alternativa, puedes especificar sus valores directamente en un estilo intercalado:

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

La práctica recomendada de establecer dimensiones se aplica a las etiquetas <img>, independientemente de si se cargan de forma diferida, pero la carga diferida puede hacer que sea más importante.

La carga diferida en Chromium se implementa de manera que es más probable que las imágenes se carguen en cuanto sean visibles, pero aún existe la posibilidad de que no se carguen en el momento adecuado. Si eso sucede, no especificar width y height en tus imágenes aumentará su impacto en el CLS. Si no puedes especificar las dimensiones de tus imágenes, cargarlas de forma diferida puede ahorrar recursos de red, pero corres el riesgo de que aumenten los cambios de diseño.

En la mayoría de los casos, las imágenes se cargan de forma diferida incluso si no especificas las dimensiones, pero hay algunos casos extremos que debes tener en cuenta. Si no se especifican width y height, las dimensiones de la imagen se establecen de forma predeterminada en 0 × 0 píxeles. Si tienes una galería de imágenes, es posible que el navegador decida que todas caben dentro del viewport al principio, ya que cada imagen no ocupa espacio y ninguna 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 lentamente.

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

También puedes cargar de forma diferida las 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>

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

Siempre carga de forma anticipada 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 especialmente para las imágenes del LCP, usa la carga anticipada predeterminada del navegador para que estén disponibles de inmediato. Para obtener más información, consulta Los efectos en el rendimiento de un exceso de carga diferida.

Usa loading=lazy solo para las imágenes que se encuentran fuera del viewport inicial. El navegador no puede cargar de forma diferida una imagen hasta que sabe dónde debe estar en la página, lo que hace que se carguen más lentamente.

<!-- 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 elegante

Los navegadores que no admiten el atributo loading lo ignoran. No obtienen los beneficios de la carga diferida, pero no hay ningún impacto negativo por incluirla.

Preguntas frecuentes

Preguntas frecuentes sobre la carga diferida a nivel del navegador

¿Puedo cargar imágenes de forma diferida automáticamente en Chrome?

Anteriormente, Chromium cargaba de forma diferida automáticamente las imágenes que eran adecuadas para diferirse si el modo lite estaba habilitado en Chrome para Android y el atributo loading no se proporcionaba o se establecía en loading="auto". Sin embargo, el modo básico y loading="auto" dejaron de estar disponibles, y no hay planes para proporcionar la carga diferida automática de imágenes en Chrome.

¿Puedo cambiar la distancia a la que debe estar una imagen del viewport antes de que se cargue?

Estos valores están codificados y no se pueden cambiar a través de la API. Sin embargo, es posible que cambien en el futuro a medida que los navegadores experimenten con diferentes distancias y variables de umbral.

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

No, solo puedes usarlo con etiquetas <img>.

El uso de loading="lazy" puede evitar que se carguen imágenes cuando no están visibles, pero se encuentran dentro de la distancia calculada. Es posible que estas imágenes se encuentren detrás de un carrusel o estén ocultas por CSS para ciertos tamaños de pantalla. Por ejemplo, Chrome, Safari y Firefox no cargan imágenes con el diseño de display: none;, ya sea en el elemento de imagen o en un elemento principal. Sin embargo, otras técnicas para ocultar imágenes, como el uso de opacity:0estilos, hacen que el navegador cargue la imagen. 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 con desplazamiento horizontal, como los carruseles. Ahora usan los mismos umbrales que el desplazamiento vertical. Esto significa que, en el caso de uso del carrusel, las imágenes se cargarán antes de que se vean en la ventana gráfica. Esto significa que es menos probable que el usuario note la carga de la imagen, pero a costa de más descargas. Usa la demostración de 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?

Con la compatibilidad total de la carga diferida integrada en los navegadores modernos, probablemente no necesites una biblioteca o una 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 tener más control sobre cuándo se activa la carga diferida.

¿Cómo manejo los navegadores que no admiten la carga diferida?

La carga diferida de imágenes a nivel del navegador es compatible con todos los navegadores principales y se recomienda para la mayoría de los casos de uso, ya que elimina la necesidad de dependencias adicionales en JavaScript.

Sin embargo, si necesitas admitir más navegadores o quieres tener más control sobre los umbrales de carga diferida, puedes usar 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 de carga diferida de JavaScript popular. Puedes detectar la compatibilidad con el atributo loading para cargar lazysizes como biblioteca de resguardo solo cuando no se admita loading. Esto funciona de la siguiente manera:

  • Reemplaza <img src> por <img data-src> para evitar una carga anticipada en navegadores no compatibles. Si se admite el atributo loading, reemplaza data-src por src.
  • Si no se admite loading, carga una alternativa de lazysizes y la inicia 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í tienes una demostración de este patrón. Pruébalo en un navegador anterior para ver la alternativa en acción.

¿La carga diferida de iframes también es compatible con los navegadores?

Browser Support

  • Chrome: 77.
  • Edge: 79.
  • Firefox: 121.
  • Safari: 16.4.

También se estandarizó <iframe loading=lazy>. Esto te permite cargar iframes de forma diferida con el atributo loading. Para obtener más información, consulta It's time to lazy-load offscreen iframes! (Es hora de cargar de forma diferida los elementos iframe fuera de la pantalla).

¿Cómo afecta la carga diferida a nivel del navegador a los anuncios en una página web?

Todos los anuncios que se muestran al usuario como imágenes o iframes se cargan de forma diferida, al igual que 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 elementos iframe se cargan de inmediato cuando se imprime la página. Consulta el problema #875403 para obtener más detalles.

¿Lighthouse reconoce la carga diferida a nivel del navegador?

Lighthouse 6.0 y las versiones posteriores tienen en cuenta los enfoques para la carga diferida de imágenes fuera de pantalla que pueden usar diferentes umbrales, lo que les permite aprobar la auditoría Diferir imágenes fuera de pantalla.

Carga diferida de imágenes para mejorar el rendimiento

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

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