While WordPress Core is working towards their own Native Lazy Loading of images, I have been using something for a while already to do the job. I’m sure I found this from, or was inspired by, someone else’s code but I don’t recall where. If it is your code, please leave a comment so that I may correctly attribute it.
The first step is to hook into the
wp_get_attachment_image_attributes filter to override the in-built
sizes attributes set by Core. We rename these attributes to
data-$attribute_name. The new image data doesn’t do anything by itself. We must move it to the correct place using a small shim in the second code snippet below: (Both snippets may be placed into your theme’s
data-$attribute_name attributes back to their original names for native lazy loading. This code detects at load time whether the browser supports native lazy loading, or we need to use something else to mimic it. In this case the fallback script we use is LazySizes.js:
You might recall, we also add the class name of
lazyload in the first snippet. So, if the browser doesn’t support native lazy loading then the
LazySizes.js fallback loads. This uses the
data-$attribute_name attributes unchanged. Those we also set in the first snippet.
If, however, the browser does support native lazy loading then we simply rewrite the
For even faster load times we set the LazySizes script to the
async load method. With this, the browser loads it asynchronously without blocking the page render. This means that the Time Till First Meaningful Paint is quicker because the browser doesn’t wait for the script to load. Once LazySizes loads, or the attributes rewritten for Native Lazy Loading, then the images pop into place as soon as they are visible. Both browser native lazy loading and LazySizes 5.0+ support loading without the page jumping about as the images are loaded. To do this, they use the
height attributes. These attributes indicate the correct aspect ratio of the image, which the browser and LazySizes use to cut out the right amount of space for the image.