Video Lazy Loading — Deferring Video Content Until Interaction
DodaTechUpdated 2026-06-288 min read
In this tutorial, you will learn about Video Lazy Loading. We cover key concepts, practical examples, and best practices to help you master this topic.
Video lazy loading defers video content until the user interacts, reducing initial page weight and improving Largest Contentful Paint scores.
What You'll Learn
By the end of this tutorial, you'll understand how video files impact page performance, how to use the loading attribute and poster images, how to replace video sources with lightweight previews, and how to implement play-on-demand patterns.
Why It Matters
Video files are the heaviest resources on the web. A single 30-second MP4 can be 5-15MB — larger than an entire page of text, images, and scripts combined. Autoplaying videos consume bandwidth and delay LCP even when not visible. Lazy loading videos ensures they download only when the user chooses to watch them.
Real-World Use
A product landing page includes three demo videos. Instead of loading all three on page load, each video shows a lightweight poster image (50KB webp). When the user clicks a video card, the poster is replaced with an embedded player that streams the video. Initial page load drops from 18MB to 800KB, and LCP improves from 4.5s to 1.2s.
Video Loading Strategies
graph LR
A[Video Loading] --> B[Poster + preload=none Recommended]
A --> C[loading=lazy attribute Chrome/Edge only]
A --> D[Intersection-based Cross-browser]
A --> E[Click-to-play Lightest approach]
A --> F[Streaming / HLS Adaptive bitrate]
B --> G[Poster image shown No video data loaded]
C --> H[Video loads when near viewport]
D --> I[Load src when video element visible]
E --> J[Load only on user click]
F --> K[Load initial segment ~2-5 seconds]
style B fill:#27ae60,color:#fff
style E fill:#27ae60,color:#fff
style C fill:#4a90d9,color:#fff
Poster + preload=none (Recommended)
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<title>Video Lazy Loading — Poster</title>
<style>
.video-container{
position:relative;
width:100%;
max-width:800px;
margin:20pxauto;
background:#000;
border-radius:8px;
overflow:hidden;
}
.video-containervideo{
width:100%;
display:block;
}
.play-button{
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
width:80px;
height:80px;
background:rgba(255,255,255,0.9);
border:none;
border-radius:50%;
cursor:pointer;
font-size:32px;
color:#1a1a2e;
transition:transform0.2s,background0.2s;
z-index:2;
}
.play-button:hover{
transform:translate(-50%,-50%)scale(1.1);
background:#ffffff;
}
</style>
</head>
<body>
<!-- preload=none: Don't load any video data until play is clicked --><!-- poster: Lightweight preview image shown instead -->
<divclass="video-container">
<videocontrolspreload="none"poster="/videos/demo-poster.webp"width="800"height="450"aria-label="Product demo video"
>
<sourcesrc="/videos/product-demo.mp4"type="video/mp4">
<p>Your browser does not support video playback.</p>
</video>
<buttonclass="play-button"aria-label="Play video">▶</button>
</div>
<script>
// Click-to-play: load video only when user clicksdocument.querySelector('.play-button').addEventListener('click',function(){
constvideo=this.previousElementSibling;
video.preload='auto';
video.load();
video.play();
this.hidden=true;
});
// Detect when native controls show (user clicked browser controls)document.querySelector('video').addEventListener('play',function(){
constbutton=this.nextElementSibling;
if(button)button.hidden=true;
});
</script>
</body>
</html>
Native loading=lazy Attribute
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<title>Video loading=lazy Demo</title>
</head>
<body>
<!-- Video 1: Above the fold — load normally -->
<videocontrolswidth="800"height="450"poster="/videos/intro-poster.webp">
<sourcesrc="/videos/intro.mp4"type="video/mp4">
</video>
<!-- Video 2: Below the fold — lazy load -->
<videocontrolsloading="lazy"width="800"height="450"poster="/videos/demo-poster.webp"
>
<sourcesrc="/videos/product-demo.mp4"type="video/mp4">
</video>
<!-- Video 3: Far below the fold — lazy load -->
<videocontrolsloading="lazy"width="800"height="450"poster="/videos/testimonial-poster.webp"
>
<sourcesrc="/videos/testimonial.mp4"type="video/mp4">
</video>
<!-- Note: loading=lazy is supported in Chrome/Edge 79+ --><!-- Falls back to normal loading in other browsers -->
</body>
</html>
// Measure video lazy loading impactasyncfunctionmeasureVideoPerformance(){
constresults={
totalVideos:0,
videosLoadedOnLoad:0,
totalVideoSize:0,
lcpImpact:null};
// Count videosconstvideos=document.querySelectorAll('video');
results.totalVideos=videos.length;
// Check which videos loaded data on page loadvideos.forEach(video=>{
if(video.readyState>0){
results.videosLoadedOnLoad++;
}
});
// Estimate video size from network entriesconstvideoResources=performance.getEntriesByType('resource')
.filter(r=>r.name.includes('.mp4')||r.name.includes('.webm'));
results.totalVideoSize=videoResources.reduce(
(total,r)=>total+(r.transferSize||0),0);
// Check LCPconstlcpEntry=performance.getEntriesByType('largest-contentful-paint');
if(lcpEntry.length>0){
results.lcpImpact=`${lcpEntry[0].renderTime.toFixed(0)}ms`;
}
results.recommendation=results.totalVideoSize>1000000?'Videos are >1MB on load. Use poster + preload=none for all non-essential videos.':'Video loading is well optimized';
returnresults;
}
Common Mistakes
Not using a poster image. Without a poster, the video element shows a black rectangle until the first frame loads. Always provide a lightweight poster image (under 100KB) for a better visual experience.
Using autoplay for above-fold videos. Autoplay videos compete with LCP elements, consume bandwidth, and annoy users if they have audio. Use poster + click-to-play for above-fold videos.
Not setting dimensions. Videos without explicit width and height cause Cumulative Layout Shift when they load. Always set width and height, or use padding-bottom percentage trick for responsive containers.
Loading all video sources in multiple formats. Each tag triggers a request to check format support. Use a single MP4 (widest support) or detect support with JavaScript before adding sources.
Forgetting mobile data users. A 10MB video on a 3G connection takes 20+ seconds to load. Always serve compressed videos (h.264/h.265), consider adaptive streaming, and show a loading indicator.
Practice Questions
What does preload=none do and when should you use it?
How does the poster attribute improve perceived performance?
What browsers support the loading=lazy attribute on videos?
How can Intersection Observer improve video loading compared to native loading=lazy?
Why is click-to-play the best approach for above-fold videos?
Challenge: Build a product gallery page with 5+ demo videos. Implement a tiered Strategy: click-to-play for the main feature video, Intersection Observer for inline demo videos, and poster-only for testimonial videos. Measure initial page weight with and without lazy loading, and track how many videos load on page load vs on interaction.
FAQ
Can I use loading=lazy on iframe embeds (YouTube, Vimeo)?
No, but you can achieve the same effect by replacing a poster image with an iframe on click. This is the recommended approach for YouTube embeds — it prevents the embed from loading any YouTube resources until the user clicks.
Does preload=none affect analytics or video tracking?
No. The video metadata (duration, dimensions) is not available until the user initiates playback. Use the play event to trigger analytics tracking instead of page load.
What about video ads?
Ad networks require their own tracking. Lazy loading videos that contain ads may delay ad impressions. Work with your ad provider to determine the best lazy loading approach for ad-supported videos.
Should I use WebM or MP4 for lazy loaded videos?
MP4 (h.264) has the widest browser support. If bandwidth is a concern, serve both with a element. Start with MP4 as the default and add WebM as an enhancement.
How do I maintain aspect ratio with lazy loaded videos?
Use the padding-bottom trick: wrap the video in a container with padding-bottom: 56.25% (for 16:9) and position the video absolutely inside. This prevents layout shift regardless of when the video loads.
Mini Project
Build a video gallery with mixed lazy loading strategies: a hero video with click-to-play and poster, inline demo videos with Intersection Observer, YouTube embeds with poster-replacement, and a performance dashboard showing bytes loaded on page load vs on demand. Compare the initial load weight and LCP scores.
What's Next
You've mastered video lazy loading. Next, learn about Lazy Loading SEO to understand the SEO implications of deferred content loading.