Follow

Follow
Shopify Lazy Load Images

Shopify Lazy Load Images

Alexander Kharchenko's photo
Alexander Kharchenko
·May 30, 2022·

2 min read

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

Low quality blured image

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);
 
Share this