<img loading="lazy"
does it without any Javascript
We are now getting more and more support for this standardized no-JavaScript method, which is very exciting!
You can see this at work in the code snippet below.
To see that the loading is actually lazy, open Chrome DevTools in the Network tab.
Then, as you scroll down the snippet, you will see that the images only load when you see them.
I've also added an optional JavaScript button to show that you can change lazy
back to the default eager
from JavaScript, and images will then start to load immediately.
document.getElementById('load-now').addEventListener('click', function(){
for (const img of document.getElementsByTagName('img')) {
img.loading = 'eager';
}
});
.separator {
height: 1000px;
width: 100px;
border: 5px solid red;
}
img {
height: 340px;
border: 5px solid black;
}
#load-now {
border: 5px solid black;
}
<div id="load-now">Click me to load all images now!</div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/5/56/Donald_Trump_official_portrait.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/8/8d/President_Barack_Obama.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/d/d4/George-W-Bush.jpeg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/d/d3/Bill_Clinton.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/9/90/George_H._W._Bush%2C_President_of_the_United_States%2C_1989_official_portrait_%28cropped%29.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/1/16/Official_Portrait_of_President_Reagan_1981.jpg"></div>
One really cool thing about this method is that it is fully SEO friendly, since the src=
attribute contains the image source as usual, see also: Lazy image loading with semantic markup
Tested in Chromium Chromium 81 and Firefox 77.0.1, both worked and loaded lazily.
IntersectionObserver
minimal runnable example
This is a JavaScript method that would work before img loading="lazy"
was implemented.
This is essentially the technique used at: https://appelsiini.net/projects/lazyload/ which was mentioned at: https://mcmap.net/q/339891/-how-do-you-make-images-load-lazily-only-when-they-are-in-the-viewport
Web APIs have evolved so much now that it is not hard to code it from scratch!
var observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0.0) {
img = entry.target;
if (!img.hasAttribute('src')) {
alert('will load the image!!!');
img.setAttribute('src', img.dataset.src);
}
}
});
},
{}
)
for (let img of document.getElementsByTagName('img')) {
observer.observe(img);
}
.separator {
height: 1000px;
width: 100px;
border: 5px solid red;
}
img {
height: 340px;
border: 5px solid black;
}
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/5/56/Donald_Trump_official_portrait.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/8/8d/President_Barack_Obama.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/d/d4/George-W-Bush.jpeg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/d/d3/Bill_Clinton.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/9/90/George_H._W._Bush%2C_President_of_the_United_States%2C_1989_official_portrait_%28cropped%29.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/1/16/Official_Portrait_of_President_Reagan_1981.jpg"></div>
Full page demo: https://cirosantilli.com/web-cheat/js-image-load-viewport.html
GitHub upstream: https://github.com/cirosantilli/cirosantilli.github.io/blob/1f637bf4791b115777300f48f427f0a6bb409fc1/web-cheat/js-image-load-viewport.html
This technique is just a combination of:
Tested in Chromium 76.
Change load order to nearest first
This is the last use case missing after loading="lazy"
for me: a method that downloads eagerly, but changes the download order to download first on viewport, then below, and then above: Change loading order of images already on page
Maybe we can do something with querySelectorAll()
to solve jQuery find next/prev elements of a certain class but not necessarily siblings and then remove loading=lazy
from images in the JavaScript! This would both degrade gracefully, and be SEO friendly.
The last issue is how to get the first visible element though:
I haven't seen a very good solution for this yet.
Lazy load video
Not sure why, but neither Chromium 81 nor Firefox 77.0.1 can lazy load video, now sure why did they do it just for img
?
Chromium 81 did implement it for iframe
however, which is what YouTube embeds use, while Firefox 77.0.1 didn't: lazy load iframe (delay src http call) with jquery