Basic
Use attribute loading
Value: eager
(default) and lazy
<img src="img.jpg" alt="Shopify Image" loading="lazy">
Advanced
Use Intersection Observer API Intersection Observers. It allows knowing when an image enters or exits the browser's viewport.
Browsers support caniuse
Polyfill IntersectionObserver
Image tag
We want to load first light preview image and add blur to make it look better.
<img
data-srcset="
{%- if image.width >= 550 -%}{{ image | img_url: '550x' }} 550w,{%- endif -%}
{%- if image.width >= 720 -%}{{ image | img_url: '720x' }} 720w,{%- endif -%}
{%- if image.width >= 990 -%}{{ image | img_url: '990x' }} 990w,{%- endif -%}
"
data-src="{{ image | img_url: '550x' }}"
src="{{ image | img_url: '50x' }}"
alt="{{ image.alt | escape }}"
loading="lazy"
class="blur"
height="{{ image.height }}"
width="{{ image.width }}"
>
.blur {
filter: blur(8px);
}
Result
Add Image Observer
const imageObserver = new IntersectionObserver(function(entries, self) {
entries.forEach(entry => {
if(entry.isIntersecting) {
if (entry.target.getAttribute('data-src')) {
const src = entry.target.getAttribute('data-src')
const srcSet = entry.target.getAttribute('data-srcset')
if (!src) {
self.unobserve(entry.target);
return;
}
const image = new Image(src);
image.src = src;
image.onload = () => {
entry.target.setAttribute('src', src);
entry.target.removeAttribute('data-src');
if (srcSet) {
entry.target.setAttribute('srcset', srcSet);
entry.target.removeAttribute('data-srcset');
}
entry.target.classList.remove("blur")
}
}
self.unobserve(entry.target);
}
});
}, {
rootMargin: '0px 0px 0px 0px',
threshold: 0.25
});
const imagesLazyLoading = () => {
const imgs = document.querySelectorAll('img[loading="lazy"]');
imgs.forEach(img => {
imageObserver.observe(img);
});
}
Pagination & Filter
In case you load your products with ajax you have to call imagesLazyLoading
again.
One of the ways to solve this create event listener.
window.addEventListener("processLazyImages", (event) => {
imagesLazyLoading();
});
// Fire event
const event = new CustomEvent("processLazyImages", {});
window.dispatchEvent(event);