Handling lazy-loaded image reflows in Shopify themes
Lazy loading images is a pretty common practice nowadays, why load all images on each page if you can't garuantee your users will actually see them? To prevent your users from downloading every image, you can instead load all images which are visible/close to being visible within the users browser viewport as they scroll.
There's a ton of libraries in the wild which implement lazy loading functionality, I'd reccomend to do some research and choose one that fits your needs or even roll your own. The only assumption I'll make here is that your markup for a lazy-loaded image looks something like this:
<img data-src="//domain.com/image.jpg" alt="" />
This image will only load when it's visible/close to being visible within the users browser viewport.
Here's a screenshot of the page we'll be building:
Here's a video of this page loading on a fast 3G connection:
Notice how initially, the copy text is visible, then once the image has loaded, the content reflows and the text gets pushed out of view underneath the image. This happens due to the browser having no knowledge of the image prior to it loading, including the image width and height.
We're working with a Shopify "image" object here which provides extra info about the image, including it's width and height; if we have access to this info prior to downloading the image in the browser, we can work out it's aspect ratio like so:
With that in place, the loading experience has dramatically improved:
Notice how the image is displayed as an empty placeholder (grey) box before the image is actually downloaded, once the image has loaded, there's no content jump because the grey box uses the same aspect ratio as the image itself.
I use this method throughout all Shopify sites I build and work on, it's such a huge performance boost with very minimal effort.
What about images which aren't "image" objects?
It's quite common to have theme references to image URLs instead of "image" objects when you use metafields to store data via a metafield editor app. Depending on the app, this method is still possible with a bit of tweaking - I make use out of Accentuate Custom Fields when I need resources to have non-global section data (e.g. each collection needs a different hero image).
While Accentuate supports an "image" field type, it's impossible for it to return an actual "image" object due to the limiations of metafields; it just returns an image URL: