Native image lazy loading has landed in Chrome, maybe don't use it
Lazy Loading Images
Web browsers are complex pieces of software, but still treat images relatively naïvely. See, for example, a section of this waterfall where almost 100 images are loaded immediately on first-view:
On this client's site all but four of the images downloading in the screenshot (shown in purple) are off-screen. Those images are totally invisble to the user on desktop and mobile, but compete for bandwidth with critical resources like the application JavaScript (yellow). Making matters even worse - browsers will download images in the order that they appear in the HTML document, and this client has a dozen images in their hero navigation menu which is at the very top of the HTML. Again, these are invisible to the user at page load time, but are loaded before the critical hero images.
Lazy loading is an approach to provide a hint (or trick) the browser so that visible images are prioritised higher than offscreen images. There have been multiple libraries which offer this functionality, see lazysizes.js. The general premise is to remove the src
attribute, so the browser does not download anything, then add a src
later in the page load which will trigger an immediate download by the browser.
Native lazy loading
As of Chrome 76, released Jul 30 2019, web developers can provide a native hint to the browser that an image can be loaded lazily by adding the attribute loading='lazy'
to the img
element. See more details on the web.dev blog.
Not ready for prime time
This release has received a lot of attention on developer twitter. Multiple tweets show developers removing their 'legacy' lazy loading approaches and replacing them with the simple loading
attribute. While adding the loading
attribute is a positive step for sites without any prior lazy loading strategy, moving to it as a replacement will almost definitely degrade overall user experience.
The browser support for loading
is less than 1% at the time of writing. This number will climb to about 60% globally once the Chrome 76 rollout to mobile and desktop completes. There will be a further ~1% increase in global support when MS Edge updates.
Safari is notably lacking from the support list. This is not a surprise, as Apple are notoriously slow to update their browser (and are opaque about roadmap), but is a serious concern for most western websites. If your Safari traffic is greater than 50%, like many of my publishing and fashion clients, moving to the loading
attribute will result in a net-negative performance change.
The future of lazy loading
The initial implementation of loading
in Chrome is not complete. There are issues with printing and exporting (looks to be resolved in v77) and the options eager
and auto
are currently identical in functionality. In the future, the plan is for auto
(the default behaviour if no loading
attribute is supplied) to be determined by the user's network conditions or data saver preference (or is it Lite Pages?). This means that the performance of your pages should be improved for users with the worst experience, but outside of your control (unless you add the attribute and set it to eager
or lazy
).
If you're not currently collecting the data saver preference in your analytics tool of choice, this could result in some confusing metrics!
Conclusions
Supporting lazy loading hints natively in the browser is a huge step forward for web performance. Using the loading
attribute as the sole approach for lazy loading will be the recommendation once WebKit and Safari implement support. For now, though, it should only be used as an enhancement and not as a replacement for existing strategies.
A great worked example was published by the BBC, where they added the loading
attribute to images in an internal app, presumably a very high proportion of Chrome Desktop traffic. The results were a 50% reduction in load time and 40 fewer requests per pageview. This is a great use case for native lazy loading.
In the interests of full disclosure, I use the loading
attribute on this site (try inspecting the images in this post). I had no lazy loading strategy beforehand, so it is a progressive enhancement. Over 70% of the traffic to this site is from Chrome, so this should be a reasonable improvement. I had previously experimented with a home-brewed lazy loading technique, but the JavaScript overhead was significant enough to negate most performance benefits.