v148 · HTML · loading="lazy"
Performance Compare
Old approach: 18 lines of JavaScript per video (IntersectionObserver setup, src swap, load call, observer disconnect). New approach: one HTML attribute. Same result.
loading="lazy" is supported in Chrome 148+, Edge 148+. The attribute is ignored gracefully
in other browsers (all videos load eagerly) — no broken experience, just no savings.
Before — IntersectionObserver
Above fold — hero text, nav
fold
video 1 — below fold
video 2 — far below fold
video 3 — far below fold
JS code required
18 lines/video
initial data loaded
0 KB
observer instances
0
Chrome 148 — loading="lazy"
Above fold — hero text, nav
fold
video 1 — loading="lazy"
video 2 — loading="lazy"
video 3 — loading="lazy"
JS code required
0 lines
initial data loaded
0 KB
observer instances
0 (browser handles)
Code comparison
Before — 18 lines per video
const videos = document.querySelectorAll(
'video[data-src]'
);
const observer = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
if (!entry.isIntersecting) return;
const video = entry.target;
video.src = video.dataset.src;
video.load();
observer.unobserve(video);
});
},
{ rootMargin: '200px' }
);
videos.forEach(v => observer.observe(v));
▲ 18 lines + data-src plumbing in HTML
Chrome 148 — 1 attribute
<!-- HTML only: -->
<video
src="clip.mp4"
loading="lazy"
poster="thumb.jpg"
controls
></video>
<!-- That's it. No JS. -->
<!-- Browser applies optimal threshold
based on connection speed,
device memory, and scroll speed. -->
▲ 1 attribute, 0 JavaScript
see also
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗