We're live-coding on Twitch! Join us!
Native Lazy-Loading Launched on Chrome 76!

Native Lazy-Loading Launched on Chrome 76!

I woke up to this amazing news this morning and couldn't think of anything better than to share with you. Given that I'm a big fan of performance optimizations, and the fact that I had written about lazy loading components with the native Intersection Observer API, it is only right that this update is brought to you.

What does lazy-loading look like?

Just add the loading="lazy" attribute to your images!

<img src="https://rickroll.jpg" loading="lazy">

Lazy-loading

For refreshers, lazy-loading is a performance optimisation technique that makes it possible to load only the required sections of your web/mobile pages on demand instead of in bulk. What this means is that for each time users scroll through your application, contents are served on demand (until they get into the viewport).

You can already imagine how that is a major improvement and performance upgrade as compared to the alternative.

Only loading non-critical, below-the-fold images and iframes when the user is likely to see them improves page load times, minimizes user bandwidth, and reduces memory usage.

Lazy-Loading Up Until Now

Until recently, the only way to implement lazy-loading is to take advantage of certain event handlers like scroll resize and orientationchange. This process wasn't very palatable to developers given that they had to take control of the applications scroll events and behaviours — and that can be really tasking.

Listening for a scroll event is not a performant way to lazy-load.

Essential Reading: Learn React from Scratch! (2019 Edition)

What then? Then comes the community intervention. Plugins and Libraries (like vanilla-lazyload) were built and made available to the public by well meaning developers who wanted to help the rest of us. Like every other good thing, it has its own set of problems. Given that these plugins uses the main thread to manage the scroll events, they bring about more performance implications since the main thread are called frequently.

Intersection Observer API

Then came the Intersection Observer API. It provided us a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document’s viewport. More importantly, it provides us a callback function that will fire when the element we are observing gets into the viewport.

As good as it sounds, you may have to deal with compatibility issues every now and then. Until today, this seemed to be the best approach in implementing lazy-loading in my opinion but, like everything else, something better always comes through.

Introducing the loading attribute

According to the release announcement, starting with Chrome 76, you'll be able to use the new `loading` attribute to lazy-load resources without the need to write custom lazy-loading code or use a separate JavaScript library. With this approach, it gives us all the benefits of the two earlier approaches without any of the consequences. You can now lazy-load images and iframes without:

  • Using any external library,
  • Writing custom lazy-loading codes or
  • Loading JavaScript on the Frontend

Let's see how that works!

<!-- only loads the resource when it gets into the viewport -->

<!-- works on images -->
<img src="image.png" loading="lazy" alt="cute-cat">

<!-- works on iframes! -->
<iframe src="https://example.com" loading="lazy"></iframe>

The loading attribute makes it possible to completely defer the loading of offscreen images and iframes until it reaches a calculated distance from the viewport by passing the lazy value to the loading attribute.

Loading Attribute Options

We can set the loading attribute to three different options:

  • lazy: lazily load the image when it gets into the viewport
  • eager: load right away (not lazy-loading at all!)
  • auto: browser will decide if it wants to lazy-load

That's not all, it still gives you the flexibility to hold on to your usual loading behaviour using the default value. In the rare case that you want to immediately load all your resources at once, you can also do that by passing the eager value to the loading attribute.

So, to implement lazy-loading of images and iframes only when they get to the viewport, you can write your HTML like this:

<!-- only loads the resource when it gets into the viewport -->

<!-- works on images -->
<img src="image.png" loading="lazy" alt="cute-cat">

<!-- works on iframes! -->
<iframe src="https://example.com" loading="lazy"></iframe>

Adding Height and Width to Prevent Reflow

It is important to add height and width attributes to the <img> element or specify their values directly in an inline style. Why? to prevent the surrounding content from reflowing when a lazy-loaded image is downloaded.

Note!! Images will still lazy-load if dimensions are not specified, but including them decreases the chance of browser reflow, hence:

<-- only loads the resource when it gets into the viewport -->


<img src="image.png" loading="lazy" alt="cute-cat" width="200" height="200">


<iframe src="https://example.com" loading="lazy"></iframe>

What if you wanted to maintain the default scroll behaviour of the browser? You can do that with this

<-- loads the resource with the default browser behaviour -->

<img src="image.png" loading="default" alt="cute-cat" width="200" height="200">
<iframe src="https://example.com" loading="default"></iframe>

But If you wanted to keep your browser’s default scroll behaviour, why bother about lazy-loading in the first place?

Finally, in the unlikely event that you want to load all your resources immediately the page loads regardless of their location, you can also do that:

<img src="image.png" loading="eager" alt="cute-cat" width="200" height="200">
<iframe src="https://example.com" loading="eager"></iframe>
<-- loads all resources immediately on page load -->

Again, this approach defeats the whole idea of lazy-loading, don't do it unless you have to

Loading iFrames

Basically, iframes can either be hidden or visible. For the loading attribute feature, Chrome handles the effect on iframes differently depending on whether the iframe is hidden or visible. Hidden iframes are often used for analytics or communication purposes.

Here's how Chrome identifies hidden iframes:

  • The iframe's width and height are 4 px or smaller.

  • display: none or visibility: hidden is applied.

  • The iframe is placed off-screen using negative X or Y positioning.

As a result, If an iframe is considered hidden, Chrome won't lazy-load it in most cases. Iframes that aren't hidden will only load when they're within the load-in distance threshold. In any case, a placeholder shows for lazy-loaded iframes that are still being fetched.

Getting Started

This feature is not yet available on a stable release however, like every other early announcement, we can start testing it out and giving valuable feedback by enabling the following flags:

  • For image lazy-loading:#enable-lazy-image-loading

  • For iframe lazy-loading#enable-lazy-frame-loading

Simply go to chrome://flags/ and search the above flags and enable them

Once enabled, you can go ahead and test out the demo prepared by the Chrome team to visualize the loading functionalities here. In my case, I rebuilt the demo just to be certain that the features are indeed working and yes it is, here's what i got:

There you go, i got the exact functionality that was promised. Now that i've confirmed that, as you can imagine, I'm going to start experimenting and trying out several use cases. I invite you to do the same and hopefully we can all find useful edge cases that will be super valuable as a feedback to the Chrome team. If you have any more questions about this feature, feel free to check out this feature FAQ section for answers to questions like:

  • Are there plans to expand this feature?
  • Can I change how close an image or iframe needs to be before a load is triggered?
  • Can CSS background images take advantage of the loading attribute?
  • Do other browsers support native lazy-loading?
  • And much more

Final thoughts

I think this is a major improvement to the way we handle lazy-loading. If this feature gets stable in Chrome 76, it will be one of the most useful releases performance-wise in a long time. I look forward to Chrome 76 and all the other goodies it'll bring.

Like this article? Follow @kenny_io on Twitter