Images | Best Practices for Page Load and Liquid Image Optimization

Solved
Highlighted
Excursionist
19 0 7

I have been looking at the: How to Manipulate Images with the img_url Filter and Using Responsive Images to Decrease Page Loading Times blog articles and I am curious what are some best practices for page load speed in terms of image optimization.

I'd like to optimize for things like:

  • Serving scaled images at the rendered size. For Example, my current image width and height at 160x99px is larger than the rendered size 53x33px. Is there a way to serve an image at 53x33px from the uploaded 160x99px image through img_url filters?
  • Cropping to element container size. Would this have advantages or disadvantages?
  • Responsive img filters vs Fixed img filters. What are best code snippets for both types for optimal image serving.

Example fixed image on collection list snippet

<!-- Original Image 160x99px -->
<!-- Image rendered at 53x33px -->
{{ collection | img_url: '53x33', crop: ‘center’, scale: 2 }}

Example of responsive image on product snippet

<img id="{{ img_id }}"
    class="tbd"
    src="{{ product | img_url: '300x300' }}"
    data-src="{{ img_url }}"
    data-widths="[180, 360, 540, 720, 900, 1080, 1296, 1512, 1728, 2048]"
    data-aspectratio="{{ product.image.aspect_ratio }}"
    data-sizes="auto"
    alt="{{ product.image.alt | escape }}">

The goal is to find the best snippet for both types that has the best user experience, optimized image weight and serves an image at the rendered size. I'm really interested to see what is being used and what are some best practices.

 

0 Likes
Highlighted
Shopify Partner
1366 24 246

This is an accepted solution.

There are few techniques out there.

I like to use the <picture> element for this, gives me more control, combined with a form of lazy load.

It depends a lot on the context, this is one way of doing this:

 

<picture class="ratio-16/9">
  <source media="(max-width: 375px)"
          srcset="{{ collection | img_url: '375x' }},
                  {{ collection | img_url: '375x', scale: 2 }} 2x">
  <source media="(max-width: 768px)"
          srcset="{{ collection | img_url: '768x' }},
                  {{ collection | img_url: '768x', scale: 2 }} 2x">
  <img src="{{ collection | img_url: '1200x' }}"
       srcset="{{ collection | img_url: '1200x' }}, {{ collection | img_url: '1200x', scale: 2 }} 2x"
       alt="..." loading="lazy">
</picture>

The sources in the picture element "tell" the browser to load on a screen size of up to 375px an image of 375px.

Up to 768px, an image of 768px.

The 2x pixel density descriptor, will tell the browser to load a high-res image for high-DPI screens.

Over that last source media query, in this case max-width: 768px, the image will have the default size of 1200px (1200 * 2 for high-DPI screens).

Those media queries and image sizes should be tweaked according to your layout.

 

The loading="lazy" hint allows you to get out of the box native lazy loading, it has a decent support of around 60%.

You can add another JS solution to get better support.

 

The last bit is the "ratio-16/9" class. When you use lazy loading the image does not have width and height information until it gets loaded.

That space will be collapsed. You want to use some CSS that will preserve the aspect ratio.

 

There are many ways of doing this, in my view there is not an one solution fits all. 

 

Few helpful links:

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture

https://web.dev/native-lazy-loading/

 

 

https://sections.design tips, tricks & Shopify sections