Native lazy loading works just fine for vertical scrolling. But I found that it doesn't when there is a horizontal scroll with an overflow-x. In that case, all the images get loaded, even if they have a fixed size.
Is that working as designed, or can it be fixed?
Native lazy loading in browsers is primarily designed for vertical scrolling scenarios. When dealing with horizontal scrolling using overflow-x, the browser may load all images to ensure smooth scrolling and avoid layout shifts, which is why all the images get loaded even if they have a fixed size. Always Use IntersectionObserver to detect when images enter the viewport and load them. If IntersectionObserver is not supported, fall back to a manual scroll event listener.
Example CSS for you;
document.addEventListener("DOMContentLoaded", function() {
let lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.classList.remove("lazy");
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
// Fallback for browsers that do not support IntersectionObserver
let active = false;
const lazyLoad = function() {
if (active === false) {
active = true;
setTimeout(function() {
lazyImages.forEach(function(lazyImage) {
if ((lazyImage.getBoundingClientRect().left <= window.innerWidth && lazyImage.getBoundingClientRect().right >= 0)) {
lazyImage.src = lazyImage.dataset.src;
lazyImage.classList.remove("lazy");
lazyImages = lazyImages.filter(function(image) {
return image !== lazyImage;
});
if (lazyImages.length === 0) {
document.removeEventListener("scroll", lazyLoad);
window.removeEventListener("resize", lazyLoad);
window.removeEventListener("orientationchange", lazyLoad);
}
}
});
active = false;
}, 200);
}
};
document.addEventListener("scroll", lazyLoad);
window.addEventListener("resize", lazyLoad);
window.addEventListener("orientationchange", lazyLoad);
}
});
.scroll-container {
display: flex;
overflow-x: auto;
white-space: nowrap;
}
.scroll-container img {
width: 200px; /*you can use any fixed size*/
height: auto;
display: inline-block;
}
<div class="scroll-container">
<img data-src="https://2.img-dpreview.com/files/p/E~C1000x0S4000x4000T1200x1200~articles/3925134721/0266554465.jpeg" alt="Image 1" class="lazy">
<img data-src="https://2.img-dpreview.com/files/p/E~C1000x0S4000x4000T1200x1200~articles/3925134721/0266554465.jpeg" alt="Image 2" class="lazy">
more here. ...
</div>