Skip to content

Instantly share code, notes, and snippets.

@atelierbram
Last active January 17, 2023 12:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atelierbram/bf428b40645b1f2ae43e809408b432ed to your computer and use it in GitHub Desktop.
Save atelierbram/bf428b40645b1f2ae43e809408b432ed to your computer and use it in GitHub Desktop.
Lazy loading video

Lazy loading video

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

You'll notice the addition of the poster attribute, which lets you specify a placeholder to occupy the <video> element's space until the video is lazy-loaded. As with the <img> lazy-loading examples, stash the video URL in the data-src attribute on each <source> element. From there, use JavaScript code similar to the Intersection Observer-based image lazy loading examples:

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) {
          for (var source in video.target.children) {
            var videoSource = video.target.children[source];
            if (typeof videoSource.tagName === "string" && videoSource.tagName === "SOURCE") {
              videoSource.src = videoSource.dataset.src;
            }
          }

          video.target.load();
          video.target.classList.remove("lazy");
          lazyVideoObserver.unobserve(video.target);
        }
      });
    });

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

To lazyload the poster image as well:

function loadVideoPoster(){
  var posterDefer = document.querySelectorAll('[data-poster]')
  for (var i=0; i < posterDefer.length; i++) {
    if(posterDefer[i].getAttribute('data-poster')){ posterDefer[i].setAttribute('poster',posterDefer[i].getAttribute('data-poster'));
    }
  }

}
addLoadEvent(loadVideoPoster);

When you lazy-load a <video> element, you need to iterate through all of the child <source> elements and flip their data-src attributes to src attributes. Once you've done that, you need to trigger loading of the video by calling the element's load method, after which the media will begin playing automatically per the autoplay attribute.

Using this method, you have a video solution that emulates animated GIF behavior, but doesn't incur the same intensive data usage as animated GIFs do, and you can lazy-load that content.

Source: web.dev/lazy-loading-video/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment