Vidéo à chargement différé

Publié le 16 août 2019, dernière mise à jour le 2 juillet 2026

Comme pour les éléments image, vous pouvez également charger les vidéos en différé. Les vidéos sont généralement chargées avec l'élément <video>, mais pour les vidéos hébergées sur d'autres services tels que YouTube, elles peuvent utiliser des <iframe> (dans ce cas, consultez l'article sur le chargement différé des iframes).

La façon de charger les <video> en différé dépend du cas d'utilisation, car il existe plusieurs solutions différentes.

Utiliser l'attribut loading

Les navigateurs ont commencé à prendre en charge l'attribut loading sur les éléments multimédias (<video> et <audio>). Lorsqu'il est compatible, cela signifie que le média et toute image de couverture sont automatiquement chargés en différé en ajoutant simplement l'attribut loading="lazy" :

<video controls loading="lazy" preload="none" poster="one-does-not-simply-placeholder.jpg">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

L'utilisation de loading="lazy" empêche le chargement de l'image poster jusqu'à ce qu'elle se trouve dans ou à proximité de la fenêtre d'affichage, puis utilise l'attribut preload pour déterminer la quantité de video à charger. Cela signifie également que les vidéos autoplay ne seront pas lues automatiquement tant qu'elles ne se trouvent pas dans ou à proximité de la fenêtre d'affichage. L'attribut loading="lazy" fonctionne avec les attributs poster, preload et autoplay, et ne les remplace pas.

Les navigateurs qui ne sont pas compatibles avec l'attribut loading sur les éléments multimédias ignorent cet attribut, ce qui entraîne le chargement immédiat de l'image poster et le chargement de la vidéo en fonction de l'attribut preload, que nous aborderons ensuite.

Utiliser l'attribut preload pour charger en différé les vidéos qui ne sont pas lues automatiquement

Il est généralement recommandé d'éviter la lecture automatique des vidéos, car cela laisse le contrôle à l'utilisateur. Dans ce cas, spécifier l'preload attribut sur l'élément <video> est le meilleur moyen d'éviter de charger l'intégralité de la vidéo jusqu'à ce que cela soit nécessaire :

<video controls loading="lazy" preload="none" poster="one-does-not-simply-placeholder.jpg">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

L'exemple précédent utilise un attribut preload avec la valeur none pour empêcher les navigateurs de précharger toutes les données vidéo, même lorsqu'elles se trouvent dans la fenêtre d'affichage. L'attribut poster attribue à l'élément <video> un espace réservé qui occupe l'espace pendant le chargement de la vidéo.

Dans la plupart des navigateurs, preload est défini par défaut sur metadata, et une partie de la vidéo est préchargée à l'aide de l'en-tête Content-Range. Cela peut entraîner le téléchargement de plus de données que souhaité. Les navigateurs ne peuvent pas savoir à quels octets les métadonnées sont stockées, et il est possible qu'elles ne soient pas stockées au début du fichier. Par conséquent, la meilleure façon d'éviter le chargement de la vidéo consiste à utiliser preload="none".

Vous pouvez améliorer cela en préchargeant les métadonnées lorsque l'utilisateur pointe sur la vidéo avec un onmouseenter attribut (ou avec le gestionnaire d'événements mouseenter équivalent) :

<video controls
  loading="lazy"
  preload="none"
  poster="one-does-not-simply-placeholder.jpg"
  onmouseenter="event.target.setAttribute('preload','metadata')">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

Cela réduit non seulement le délai lorsque l'utilisateur lance la lecture de la vidéo, mais affiche également sa durée dès qu'il pointe dessus.

Les vidéos peuvent être considérées comme des candidats LCP. Une poster image se chargera plus rapidement que la vidéo. Par conséquent, si elle est un candidat LCP, vous devez utiliser une image de couverture, mais aussi la précharger avec une valeur d'attribut fetchpriority de "high", car au moment de la rédaction, vous ne pouvez pas spécifier la fetchpriority pour les attributs de couverture :

<link rel="preload" href="one-does-not-simply-placeholder.jpg" as="image" fetchpriority="high">
<video controls preload="none"
  poster="one-does-not-simply-placeholder.jpg"
  onmouseenter="event.target.setAttribute('preload','metadata')">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

Les vidéos qui sont des éléments LCP ne doivent pas utiliser loading="lazy" de la même manière que vous ne devez pas charger en différé les images LCP vidéos.

Pour les vidéos qui remplacent les GIF animés

Les vidéos lues automatiquement sont couramment utilisées pour les animations rapides de type GIF. Bien que les GIF animés soient largement utilisés, ils sont inférieurs aux équivalents vidéo à plusieurs égards, en particulier en termes de taille de fichier. Les GIF animés peuvent atteindre plusieurs mégaoctets de données. Les vidéos de qualité visuelle similaire ont tendance à être beaucoup plus petites.

L'utilisation de l'élément <video> pour remplacer un GIF animé n'est pas aussi simple que l'élément <img>. Les GIF animés présentent trois caractéristiques :

  1. Ils sont lus automatiquement lorsqu'ils sont chargés.
  2. Ils sont lus en boucle (mais ce n'est pas toujours le cas).
  3. Ils n'ont pas de piste audio.

Voici comment obtenir ce résultat avec l'élément <video> :

<video autoplay muted loop playsinline>
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

L'attribut loading="lazy" évite de charger la vidéo jusqu'à ce qu'elle se trouve à proximité de la fenêtre d'affichage. Les attributs autoplay, muted et loop sont explicites. playsinline est nécessaire pour que la lecture automatique se produise dans iOS.

Vous disposez désormais d'un remplacement de GIF par une vidéo utilisable sur toutes les plates-formes. Mais comment le charger en différé ?

Pour les navigateurs compatibles, loading="lazy" est l'option la plus simple :

<video loading="lazy" autoplay muted loop playsinline>
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

Pour prendre en charge le chargement différé des vidéos dans d'autres navigateurs, vous devez utiliser JavaScript et modifier votre <video> balisage en conséquence :

<video class="lazy" preload="none" controls muted loop playsinline width="610" height="254" poster="one-does-not-simply.jpg">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

Vous remarquerez la suppression de autoplay et l'ajout des attributs class="lazy", preload="none" et poster, qui vous permettent de spécifier un espace réservé pour occuper l'espace de l'élément <video> jusqu'à ce que la vidéo soit chargée en différé. Ensuite, nous utilisons un observateur d'intersection JavaScript pour réactiver la lecture automatique :

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

  if ("IntersectionObserver" in window) {
    var lazyVideoObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(video) {
        if (video.isIntersecting) {
          video.target.removeAttribute('preload');
          video.target.removeAttribute('controls');
          video.target.autoplay = true;
          video.target.classList.remove("lazy");
          lazyVideoObserver.unobserve(video.target);
        }
      });
    });

    lazyVideos.forEach(function(lazyVideo) {
      lazyVideoObserver.observe(lazyVideo);
    });
  }
});

Avec cette méthode, la vidéo n'est pas lue automatiquement par défaut, mais uniquement lorsque l'observateur d'intersection détecte que la vidéo entre dans la fenêtre d'affichage. De plus, l'attribut controls gère les cas où JavaScript échoue. Ensemble, cela signifie que vous disposez d'une solution vidéo qui émule le comportement des GIF animés, mais qui n'entraîne pas la même utilisation intensive des données que les GIF animés, et que vous pouvez charger ce contenu en différé.

Bibliothèques de chargement différé

Les bibliothèques suivantes peuvent vous aider à charger les vidéos en différé :

  • vanilla-lazyload et lozad.js sont des options très légères qui n'utilisent que l'observateur d'intersection. Par conséquent, elles sont très performantes, mais doivent être polyfillées avant de pouvoir être utilisées sur les anciens navigateurs.
  • Si vous avez besoin d'une bibliothèque de chargement différé spécifique à React, vous pouvez envisager d'utiliser react-lazyload. Bien qu'elle n'utilise pas l'observateur d'intersection, elle fournit une méthode familière de chargement différé des images pour les personnes habituées à développer des applications avec React.

Chacune de ces bibliothèques de chargement différé est bien documentée et comporte de nombreux modèles de balisage pour vos différentes tentatives de chargement différé.

À mesure que l'attribut loading pour <video> sera disponible dans davantage de navigateurs, nous nous attendons à ce que les solutions JavaScript (y compris les bibliothèques) soient moins utilisées au profit des solutions intégrées, à l'exception de celles qui souhaitent plus de contrôle que ce qui est autorisé.