v147 · 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 147+, Edge 147+. 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 147 — 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)
invalid value fallback
If a page ships loading="lazyish" by mistake, browsers preserve the content attribute but expose the IDL property as eager. That means the performance budget should treat the media as not lazily loaded.
Click the button to test invalid values.
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 147 — 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 ↗