14 November 2019
The new native lazy loading for images and iframes in Chromium-based browsers
In my previous article about lazy loading, we’ve learned that implementing it into a website requires using a third-party JavaScript library and modifying your application to be supported (or writing a custom solution yourself). Luckily, help is on its way – all this might change for the better thanks to a new proposal of native lazy loading that’s already available in the latest Chromium-based browsers! Let’s see what it has to offer.
Check out my previous article on lazy loading if you haven’t already. Otherwise, let’s get to native lazy loading in Chromium-based browsers.
TL;DR?
Add a loading=”lazy”
attribute to img
or iframe
tags that you want to load on demand. The browser will load these when users scroll near the element.
And here’s how it works:
Now, how did we get there?
Graphic assets are often the most significant part of the data required to display a page. Completely understandable from the UX/UI point of view though – they make your website look more appealing to the users. While these assets are needed, some of them may be off-screen. That makes it possible to defer loading them to the time when they are actually required – when a user scrolls down and is near seeing them. That operation of deferring loading resources is called lazy loading (or “on-demand” loading).
It’s always been quite tricky to implement lazy loading because of the need for writing additional JavaScript logic or using external libraries and modifying an application to support it.
Now we have a new option – a native implementation that just works and can be used easily by developers right at the time of adding new elements.
And by a fact that’s just an attribute, it can be used with every frontend framework. That’s something I’ve been waiting for.
Read more: A guide to Svelte – what can the rising frontend framework do for you?
Attribute specification
The full specification can be found in a proposal pull request on GitHub and I strongly encourage you to read the discussion there in order to see how it looks like to propose a new attribute to a living specification and what you need to think about. However, it’s not required to get to know how the loading
attribute works, and we can just jump straight into values we have available:
lazy
– flags asset as a good candidate to be loaded lazily,eager
– forces asset to load straight away disabling lazy-loading,auto
(or value not set) – leaves the decision to a browser.
What about scrolling?
Scroll distance threshold
All images and iframes above the fold (being visible without scrolling) load normally, others are loaded when the user scrolls near them. The distance when elements should begin loading is dynamic and depends on:
- Connection type (e.g. 3g, 4g, unknown),
- Type of resource (image or iframe),
- Whether Lite Mode is enabled in Chrome for Android.
Currently, these values are hardcoded in Chromium’s source and can be overridden only using command line arguments. It may seem like a big issue of the native implementation but actually, it has one substantial advantage – it depends on the effective connection type of user’s device. It would require a lot of work to detect it correctly and we can assume that the values provided by authors of that feature are calculated correctly, so we don’t need to worry about it.
Note: Chrome 77 allows to experiment how different connection types are affecting distance threshold by setting network throttling in DevTools.
Lazy images
To make the native lazy loading work, you need to add a single attribute – loading="lazy"
to an img
element. However, you may want to prevent browser reflow when the image is loaded by adding dimensions to it (width
and height
attributes) or using styles.
Lazy iframes
iframe
elements work slightly different than images. Chrome firstly checks whether the element is hidden (is/isn’t a good candidate to be lazily loaded). Chrome considers the element as hidden when:
- the element’s width and height are 4px or smaller,
display: none;
orvisibility: hidden;
is set,- the element is off-screen using negative positioning values.
Iframes that aren’t labeled as hidden load when a user scrolls near them (like images).
Read more: JavaScript static site generators: let’s build a website from scratch!
What about the onload
event?
Lazily loaded image and iframe element’s onload
events are triggered – as you might expect – when data is completely loaded. So when the element is lazily loaded, onload
fires as a user scrolls near it, and the data is fetched.
The document’s onload
event works a little bit differently. Traditionally, the event has been fired when all images and iframes were already loaded. With lazy loading, the document doesn’t wait for deferred, off-screen elements to be loaded before triggering the event.
Lazy loading browser support
Currently, the native lazy loading feature has shipped with Chrome 76 stable release and is available in all Chrome 76+ based browsers. By the time of writing this article, I was able to use native lazy loading in Chrome, Opera, and Microsoft Edge Beta. There’s also an open implementation ticket for Firefox.
Feature detection
You can easily detect if native lazy loading is present by checking the loading
property – it’s defined in prototypes of HTMLImageElement
and HTMLIFrameElement
:
Examples of loading
attribute
Here are some examples of using the new loading
attribute that show how easy it is to actually use the feature.
What’s the future of native lazy loading?
Native Lazy Loading is a new proposal that might become a standard one day. Thankfully it’s been implemented in Chrome, and there are easy ways to polyfill it. I encourage you to play with the new loading
attribute to get to know it. If you need full browser support, you might want to prepare a fallback to an old method using JavaScript. If you’re interested in that, I’ve already published an article about traditional lazy loading implementation in JS and React.