I recently redesigned my personal site and the first version was very lean. As I started adding content to pages and writing new blog posts, it made sense to implement image lazy-loading to improve performance.

There are many JS-based solutions for image lazy-loading but I did not want to invest time in finding the best one. So, I quickly decided to go for native lazy-loading.

Browser support for native lazy-loading is currently limited but support in Opera and Chrome is good enough for me.

Implementing native lazy-loading is easy: simply add loading="lazy" to img elements. Awesome!

I commited the change, deployed my Eleventy-powered site to Netlify and then tested how images load in Chrome. I was disappointed.

Chrome fetches all the images on my homepage on page load, while none of the images are above the fold on mobile and only some on desktop.

What is Chrome’s native image lazy-loading logic?

When does Chrome decide to fetch a below-the-fold loading="lazy" image?
Being disappointed with what I saw on my own site, I set out to find the answer to this question, like so:

  • find a very long blog post that has loading="lazy" images at the bottom: An In-Depth Tutorial of Webmentions + Eleventy
  • load the page in Chrome, then clear the Network panel
  • scroll down, a few hundred pixels at a time until those lazy-loaded images are fetched
  • in console, get the value of window.pageYOffset
  • scroll down until the top of the lazy-loaded images become visible

I see the lazy-loaded images being fetched at ~ window.pageYOffset = 8500 on desktop and they become visible at ~ window.pageYOffset = 11500. So, the image lazy-load logic of Chrome seems to be: if the image is 3000 or less pixels below the viewport, load it.

3000 pixels… that is a lot!

Load-in distance threshold

It’s always good to compare test results against the spec or official documentation.

I read the native lazy-loading explainer article on web.dev. The section Load-in distance threshold states:

All images and iframes that are above the fold—that is, immediately viewable without scrolling—load normally. Those that are far below the device viewport are only fetched when the user scrolls near them.

That section in the article also mentions the “distance threshold is not fixed and varies depending on several factors”. These factors include the type of resource being fetched (image or iframe), whether Lite mode is enabled on Chrome for Android and the effective connection type.

Thankfully, there is also a link to the relevant code in Chromium source: Lazy image loading distance-from-viewport thresholds for different effective connection types.

The code is easy to read and confirms my findings: if the effective connection type is 4g, Chrome will fetch images with loading="lazy" when they are within 3000 pixels of the current scroll position.

A Better Lazy-Loading Logic

On my 13 inch macbook, with Dock positioned on the left, the viewport height in Chrome is 786 pixels so images with loading="lazy" that are more than 4x the viewport down the page are eagerly fetched by Chrome on page load.

In my opinion, that is waaaaay too eager. Why not use a lower threshold value like 1000 pixels? Or even better: base the threshold value on the actual viewport height.

I will file a bug with Chromium soon and see where that leads.

If I would need to implement image lazy-loading on a high-traffic e-commerce site today, I’d very likely go for a JS-based solution. Partly because the native solution only works in Chrome, but also because Chrome’s implementation is too eager and therefore not so effective.


Aaron Peters photo

Aaron Peters (@aaronpeters) is a freelance web performance consultant since 2009 and co-founder of Multi-CDN provider TurboBytes and CDN Planet.

21 Responses to “Native Image Lazy Loading in Chrome Is Way Too Eager”

  1. Barry

    Nice investigation but I’m not sure I agree to be honest. One of the things I hate about lazy loading is the noticeable delay when scrolling down so think there is a balance. This is respectably true on fast computers/connections where lazy loading can actually make a site feel slower – surely the opposite of the intention of this feature!

    By taking the Effective Connection Type into account I think they strike a good balance here and 4G connection or higher suggests plenty of bandwidth (though admittedly nothing to say the cost of that bandwidth!) and think it should be quite eager in that case to avoid the first point I made.

  2. Dario

    Yeap, I also reached the same conclusion, in our case we left the native lazyload for images that need to be indexed (as SEO strategy), and continue to use the javascript lazyload for all the rest since gives me more control over the thresholds. I don’t understand why Chrome does not give some override control to the developers since only a bunch of us that knows what this is are going to use it anyway.
    Is there any way to vote your “bug/lack of feature” in Chrome to be voted? Thanks!

  3. Aaron Peters

    @Barry “… One of the things I hate about lazy loading is the noticeable delay when scrolling down …” . I feel the same, so the challenge is to implement a logic / thresholds that find optimal balance and imho Chrome does not have that today. Lower thresholds, e.g. 3000 becomes 1500, should be just as good for most user experiences but a lots less data is fetched early.
    The cost of the bandwidth is something we should not take lightly. I know many people who have fast 4G on their phones but also a limited, small data plan (1 GB/m).

  4. Aaron Peters

    @Dario, why does Chrome not allow devs to set their own thresholds for their website? Well, one argument can be: Keep It Simple. Don’t let devs even think about the thresholds. On the other hand, the self-set thresholds can be option.

    I will post a comment here, and on Twitter, once I filed the bug report with Chromium.

  5. Alena Mage

    Yes, sometimes I also feel about lazy loading issues. That’s the way chrome is way to eager and enhance.

  6. Karl

    I guess when Google puts that much emphasis on making websites appear as fast as possible to all visitors through various mechanisms (critical css, ttf, dns preload, cdn, http/2), it’s kinda counter-productive if they didn’t also preload a generous amount of images after page load, to be available on scroll.

    Let’s face it. If you are on a standard modern wifi connection, it’s unlikely you would see any negative effects of a website loading images 3000 px below the viewport.

  7. Mikael Gramont

    I see here that there are several factors that Chrome takes more than just page offset into account: https://web.dev/native-lazy-loading/

    I couldn’t find any reference to a standard for how this works though, it kind of looks like Google is out there doing their own thing. Which would suck because you can pretty much assume Safari will behave totally differently for business reasons, and Firefox will be doing something else too.

    This is a complex problem, and I don’t think a single algorithm will suit everyone’s needs. We’d benefit from listing the different scenarios and corresponding user expectations before making assessments.

    For example, I see people mention the fact that they are annoyed by the fact that they load up a page and get on a train without network coverage, scroll and see missing images. Others say they hate seeing images being rendered as they are still loading.

    I’d love to see a standard list of scenarios, with matching browser behaviors that could be triggered by sending a response header or meta. Things like:

    x-lazy-load-minimal => careful lazy-load images, low distance threshold
    x-lazy-load-eager => less careful lazy-load images, higher distance threshold
    x-lazy-load-disable => disable lazy-loading, load everything as usual

  8. Native Image Lazy Loading in Chrome Is Way Too Eager – Bram.us

    […] Native Image Lazy Loading in Chrome Is Way Too Eager → […]

  9. Les tendances et les défis webperf pour 2020 - Fasterize

    […] si cette première implémentation de Chrome est sujette à débat, les premières pierres de l’édifice sont en […]

  10. Native Image Lazy Loading in Chrome Is Way Too Eager | Ozzie Bock Says

    […] Interesting research from Aaron Peters on <img loading="lazy" … >: […]

  11. Wordpress: Kein Lazyload-Plugin mehr notwendig? | protoSTERN

    […] anfängliche Begeisterung wurde deutlich gedämpft, nachdem ich diesen Blogartikel von Aaron Peters gelesen habe. Grund dafür ist seine Feststellung, das Chrome Bilder mit lazy-load […]

  12. Native Image Lazy Loading in Chrome Is Way Too Eager – CodingNova

    […] Interesting research from Aaron Peters on <img loading="lazy" … >: […]

  13. NN

    I’ll also continue to use a javascript solution for now. Not only this is a Chrome-only feature at the moment, but we can’t control the threshold and that’s a problem for me.

    One of my sites contains a lot of images (they are the content). This means that pages are heavy (2-10MB), so lazy loading is a requirement. At the same time, most users use a mobile device and 3G-4G. After some complaints, I had to change the trigger from 300 to 2000px. It’s a lot, but on slower connections it’s the only way to ensure that heavy images are loaded (or almost) when they reach the viewport.

    On a different site, images don’t matter as much and I use 100px because it’s not a problem if it takes a second or two for them to load.

    This is a hard thing to fix. Lazy load helps with loading speed and reduces data usage, but images sometimes take too long to load and users may experience scrolling lag. Not to mention that it will disappoint some users when they lose data and images aren’t there.

    I find it hard to use this feature without being able to set a threshold and I doubt they can find a solution that works well for all sites.

  14. Native Image Lazy Loading in Chrome Is Way Too Eager – Technology Blog

    […] Interesting research from Aaron Peters on <img loading="lazy" … >: […]

  15. jz

    The browser seems like the right place to solve this problem – the user agent has more information than site authors, the people designing the algorithms there are the most skilled engineers in the business, and they’re incentivized to make the right choice for the user.

    It’s been mentioned in a few other comments but if Chrome seems too eager to you, you’re probably discounting important data points like the connection type, user preference to save data etc.. – in general people don’t want to wait for things, so all other things being nominal it’s probably a better user experience to eagerly load things even if they’re pretty far down the page.

    I think users probably don’t really want this behavior to vary from site to site but of course you’re free to not opt into the standard experience on your site if you really think you can do a better job.

  16. Inconsistent user-experiences with native lazy-loading images | Ctrl blog

    […] behavior has been called “too eager”, and I tend to agree. However, Gecko’s behavior seems too lazy. I believe the ideal default […]

  17. Jeremy

    Not only is Chrome too eager but the default threshold values are ass-backwards. i.e.:

    name: "lazyImageLoadingDistanceThresholdPxUnknown",
    initial: 5000,
    type: "int",
    name: "lazyImageLoadingDistanceThresholdPxOffline",
    initial: 8000,
    type: "int",
    name: "lazyImageLoadingDistanceThresholdPxSlow2G",
    initial: 8000,
    type: "int",
    name: "lazyImageLoadingDistanceThresholdPx2G",
    initial: 6000,
    type: "int",
    name: "lazyImageLoadingDistanceThresholdPx3G",
    initial: 4000,
    type: "int",
    name: "lazyImageLoadingDistanceThresholdPx4G",
    initial: 3000,
    type: "int",

    So if you’re on a slow 2G connection Chrome will try to immediately load anything within 8000px of your current scroll position. So the slower your connection and/or the more bandwidth limited you are, the more images it will load up front without waiting to lazy load them.

    I can maybe understand this decision in that the browser is being conservative in trying to avoid you ever seeing a missing image. But I thought the whole idea of lazy loading was to avoid unnecessarily loading content you may never see, and ultimately conserve bandwidth. Therefore it should be more aggressive in lazy loading images on restricted bandwidth connections. The choice to set those defaults in that context makes no sense to me.

  18. Jennifer Bell

    Well written post.

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
And here's a tool to convert HTML entities