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 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.

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 a little demo:

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.

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; or visibility: hidden; is set,

the element is off-screen using negative positioning values.

Iframes that aren’t labelled 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.

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.

Summary

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.

Read more: Code splitting with React & Webpack: advanced app optimisation