<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/