Images à chargement différé

Les images peuvent apparaître sur une page Web, car elles sont intégrées dans le code HTML en tant qu'éléments <img> ou en tant qu'images de fond CSS. Dans cet article, vous découvrirez comment effectuer le chargement différé des deux types d'images.

Images intégrées

Les options de chargement différé les plus courantes sont les images utilisées dans les éléments <img>. Avec les images intégrées, nous proposons trois options de chargement différé, que vous pouvez utiliser en combinaison pour garantir une compatibilité optimale entre les navigateurs:

Utiliser le chargement différé au niveau du navigateur

Chrome et Firefox sont tous deux compatibles avec le chargement différé avec l'attribut loading. Cet attribut peut être ajouté aux éléments <img>, ainsi qu'aux éléments <iframe>. La valeur lazy indique au navigateur de charger l'image immédiatement si elle se trouve dans la fenêtre d'affichage, et d'extraire d'autres images lorsque l'utilisateur fait défiler la page à proximité.

Consultez le champ loading du tableau sur la compatibilité des navigateurs de MDN pour en savoir plus sur les navigateurs compatibles. Si le navigateur n'est pas compatible avec le chargement différé, l'attribut est ignoré et les images sont chargées immédiatement, normalement.

Pour la plupart des sites Web, ajouter cet attribut aux images intégrées améliorera les performances et évitera aux utilisateurs de charger des images sur lesquelles ils ne pourront peut-être jamais faire défiler la page. Si vous disposez d'un grand nombre d'images et que vous souhaitez vous assurer que les utilisateurs de navigateurs qui ne sont pas compatibles avec le chargement différé, vous devez associer cette fonctionnalité à l'une des méthodes décrites ci-dessous.

Pour en savoir plus, consultez Chargement différé au niveau du navigateur pour le Web.

Utiliser l'observateur d'intersection

Pour émuler le chargement différé des éléments <img>, nous utilisons JavaScript pour vérifier s'ils se trouvent dans la fenêtre d'affichage. Si c'est le cas, leurs attributs src (et parfois srcset) sont renseignés avec les URL du contenu image souhaité.

Si vous avez déjà écrit du code de chargement différé, vous avez peut-être accompli votre tâche en utilisant des gestionnaires d'événements tels que scroll ou resize. Bien que cette approche soit la plus compatible avec tous les navigateurs, les navigateurs récents offrent un moyen plus performant et plus efficace de vérifier la visibilité des éléments via l'API Intersection Observer.

Intersection Observer est plus facile à utiliser et à lire que le code en s'appuyant sur divers gestionnaires d'événements, car il vous suffit d'enregistrer un observateur pour surveiller les éléments plutôt que d'écrire un code fastidieux de détection de la visibilité des éléments. Il vous suffit de décider quoi faire lorsqu'un élément est visible. Supposons que ce modèle de balisage de base soit utilisé pour vos éléments <img> à chargement différé:

<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!">

Il y a trois éléments pertinents de ce balisage sur lesquels vous devez vous concentrer:

  1. L'attribut class, avec lequel vous sélectionnerez l'élément en JavaScript.
  2. L'attribut src, qui référence une image d'espace réservé qui s'affiche lors du premier chargement de la page.
  3. Les attributs data-src et data-srcset, qui sont des attributs d'espace réservé contenant l'URL de l'image que vous chargez une fois l'élément dans la fenêtre d'affichage.

Voyons maintenant comment utiliser Intersection Observer en JavaScript pour charger des images en différé à l'aide de ce modèle de balisage:

document.addEventListener("DOMContentLoaded", function() {
  var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));

  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.srcset = lazyImage.dataset.srcset;
          lazyImage.classList.remove("lazy");
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  } else {
    // Possibly fall back to event handlers here
  }
});

Dans l'événement DOMContentLoaded du document, ce script interroge le DOM pour tous les éléments <img> avec une classe de lazy. Si l'observateur d'intersection est disponible, créez un observateur qui exécute un rappel lorsque des éléments img.lazy entrent dans la fenêtre d'affichage.

Intersection Observer est disponible dans tous les navigateurs récents. Par conséquent, l'utiliser comme polyfill pour loading="lazy" garantit que le chargement différé sera disponible pour la plupart des visiteurs.

Images en CSS

Bien que les balises <img> soient le moyen le plus courant d'utiliser des images sur les pages Web, les images peuvent également être appelées via la propriété CSS background-image (et d'autres propriétés). Le chargement différé au niveau du navigateur ne s'applique pas aux images de fond CSS. Vous devez donc envisager d'autres méthodes si vous disposez d'images de fond à charger en différé.

Contrairement aux éléments <img> qui se chargent quelle que soit leur visibilité, le comportement de chargement des images en CSS est plus spéculatif. Lorsque les modèles de document et d'objet CSS et l'arborescence de rendu sont créés, le navigateur examine comment le code CSS est appliqué à un document avant de demander des ressources externes. Si le navigateur a déterminé qu'une règle CSS impliquant une ressource externe ne s'applique pas au document tel qu'il est en cours de construction, il ne la demande pas.

Ce comportement spéculatif peut être utilisé pour différer le chargement des images en CSS en utilisant JavaScript pour déterminer quand un élément se trouve dans la fenêtre d'affichage, puis en appliquant à cet élément une classe qui applique un style en appelant une image de fond. Ainsi, l'image est téléchargée au moment opportun et non lors du chargement initial. Prenons l'exemple d'un élément qui contient une grande image de fond de héros:

<div class="lazy-background">
  <h1>Here's a hero heading to get your attention!</h1>
  <p>Here's hero copy to convince you to buy a thing!</p>
  <a href="/buy-a-thing">Buy a thing!</a>
</div>

L'élément div.lazy-background contient normalement l'image de fond héros appelée par du code CSS. Toutefois, dans cet exemple de chargement différé, vous pouvez isoler la propriété background-image de l'élément div.lazy-background via une classe visible ajoutée à l'élément lorsqu'il se trouve dans la fenêtre d'affichage:

.lazy-background {
  background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}

.lazy-background.visible {
  background-image: url("hero.jpg"); /* The final image */
}

À partir de là, utilisez JavaScript pour vérifier si l'élément se trouve dans la fenêtre d'affichage (avec Intersection Observer) et ajoutez ensuite la classe visible à l'élément div.lazy-background, qui charge l'image:

document.addEventListener("DOMContentLoaded", function() {
  var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));

  if ("IntersectionObserver" in window) {
    let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add("visible");
          lazyBackgroundObserver.unobserve(entry.target);
        }
      });
    });

    lazyBackgrounds.forEach(function(lazyBackground) {
      lazyBackgroundObserver.observe(lazyBackground);
    });
  }
});

Effets sur le LCP (Largest Contentful Paint)

Le chargement différé est une excellente optimisation qui réduit la consommation globale des données et les conflits sur le réseau au démarrage en reportant le chargement des images au moment où elles sont réellement nécessaires. Cela peut améliorer le temps de démarrage et réduire le traitement sur le thread principal en réduisant le temps nécessaire au décodage des images.

Cependant, le chargement différé est une technique qui peut avoir un impact négatif sur le LCP Largest Contentful Paint de votre site Web si vous êtes trop enthousiaste à l'idée d'utiliser cette technique. Vous devez éviter d'utiliser les images au chargement différé qui se trouvent dans la fenêtre d'affichage au démarrage.

Lorsque vous utilisez des chargeurs différés basés sur JavaScript, évitez le chargement différé des images dans la fenêtre d'affichage, car ces solutions utilisent souvent un attribut data-src ou data-srcset comme espace réservé pour les attributs src et srcset. Le problème est que le chargement de ces images sera retardé, car l'outil d'analyse de préchargement du navigateur ne les trouve pas au démarrage.

Même l'utilisation du chargement différé au niveau du navigateur pour charger une image dans la fenêtre d'affichage peut se retourner contre lui. Lorsque loading="lazy" est appliqué à une image dans la fenêtre d'affichage, cette image est retardée jusqu'à ce que le navigateur sache qu'elle se trouve dans la fenêtre d'affichage, ce qui peut affecter le LCP d'une page.

N'utilisez jamais le chargement différé des images visibles dans la fenêtre d'affichage au démarrage. C'est un modèle qui aura une incidence négative sur le LCP de votre site et, par conséquent, sur l'expérience utilisateur. Si vous avez besoin d'une image au démarrage, chargez-la le plus rapidement possible en évitant de la charger de manière différée.

Bibliothèques à chargement différé

Dans la mesure du possible, utilisez le chargement différé au niveau du navigateur. Toutefois, si vous vous trouvez dans une situation où cela n'est pas possible (par exemple, si un grand nombre d'utilisateurs dépend toujours d'anciens navigateurs), vous pouvez utiliser les bibliothèques suivantes pour le chargement différé des images:

  • lazysizes est une bibliothèque complète de chargement différé qui permet de charger en différé les images et les iFrames. Le modèle utilisé est assez semblable aux exemples de code présentés ici, car il se lie automatiquement à une classe lazyload sur les éléments <img> et exige que vous spécifiiez des URL d'image dans les attributs data-src et/ou data-srcset, dont le contenu est respectivement remplacé par les attributs src et/ou srcset. Il utilise Intersection Observer (que vous pouvez polyfill) et peut être étendu avec un certain nombre de plug-ins pour effectuer des opérations telles que le chargement différé de vidéos. En savoir plus sur l'utilisation des tailles différées
  • vanilla-lazyload est une option légère pour les images à chargement différé, les images de fond, les vidéos, les iFrames et les scripts. Il exploite Intersection Observer, prend en charge les images responsives et active le chargement différé au niveau du navigateur.
  • lozad.js est une autre option légère qui n'utilise qu'Intersection Observer. Il est donc très performant, mais il devra être émulé avant de pouvoir être utilisé dans des navigateurs plus anciens.
  • Si vous avez besoin d'une bibliothèque de chargement différé spécifique à React, envisagez d'utiliser react-lazyload. Bien qu'il n'utilise pas Intersection Observer, il fournit une méthode de chargement différé des images familière, destinée aux personnes habituées au développement d'applications avec React.