Lazy Loading Image Overview
Different techniques
How to achieve better UX
Future native support
Around 40%- 50% size of a web page is image! (source)
*Based on HTTPArchive
1. Prevent image loading:
2. Trigger the load when image is in viewport
Don't set the src url to image
<img data-src="https://ik.imagekit.io/demo/default-image.jpg" />
Set src when image is in viewport
const lazyImages = document.querySelectorAll('img.lazy-image');
lazyImages.forEach((image, index) => {
if (isInViewport(image)) {
image.src = image.getAttribute('data-src');
image.classList.remove("lazy-image");
}
});
.lazy-image {
background: #F1F1FA;
}
.background-image {
background-image: url('https://ik.imagekit.io/demo/img/image10.jpeg?tr=w-600,h-400');
}
Toggle class name to add background-image
getBoundingClientRect() API
function loadLazyImage() {
const lazyImages = document.querySelectorAll('img.lazy-image');
lazyImages.forEach((lazyImage, index) => {
if (isInViewport(lazyImage)) {
setImageSrc(lazyImage);
}
});
}
document.addEventListener("scroll", loadLazyImage);
window.addEventListener("resize", loadLazyImage);
const lazyImages = document.querySelectorAll('img.lazy-image');
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const image = entry.target;
setImageSrc(image);
imageObserver.unobserve(image);
}
});
});
// Observe all lazy images
lazyImages.forEach(image => {
imageObserver.observe(image);
});
Scale to 200 byte
Send in GraphQL response
User scrolls fast
Preload image
Janky effect of partial render
Defer until ready
src is set
download image
decode image
render image
const newImage = document.createElement('img');
newImage.setAttribute('src', image.getAttribute('data-src'));
newImage.classList.add('image');
newImage.decode().then(() => {
image.parentNode.replaceChild(newImage, image);
});
Native support for lazy image in browser is coming...
<img src="celebration.jpg" loading="lazy" alt="..." />
<iframe src="video-player.html" loading="lazy"></iframe>
<script>
if ('loading' in HTMLImageElement.prototype) {
// Browser supports `loading`..
} else {
// Fetch and apply a polyfill/JavaScript library
// for lazy-loading instead.
}
</script>