9

I'm able to add the loading="lazy" attribute on individual images, or with JavaScript and apply them all at once.

But, when I do it with JavaScript, and then inspect the page, I see the images load on page load, but each image has the attribute attached.

Why does adding loading="lazy" with HTML load the image lazily, but adding the attrib with JavaScript doesn't provide the lazy loading behavior?

let img = document.querySelectorAll('img');
for (let i = 0; i < img.length; i++) {
  let images = img[i];
  images.setAttribute('loading', 'lazy');
}
img {
  max-width: 100%;
  height: auto;
}

.container {
  margin-top: 2000px;
}
<div class="container">
  <img src="https://images.unsplash.com/photo-1481349518771-20055b2a7b24">
  <img src="https://images.unsplash.com/photo-1494253109108-2e30c049369b">
  <img src="https://images.unsplash.com/photo-1494232410401-ad00d5433cfa">
</div>

7
  • 10
    The JavaScript doesn't run until after the images have already started loading. So it's too late to make them load lazily. Commented Nov 3, 2021 at 4:59
  • So running that particular script in the head would do the trick. Commented Nov 3, 2021 at 5:01
  • 4
    If you run it in the head then it won't be able to find the DOM elements to change their attributes. Commented Nov 3, 2021 at 5:02
  • Any ideas on this? I have many images on my site that I need to apply this to... like hundreds. Commented Nov 3, 2021 at 5:04
  • 1
    Can you change the src attribute before it reaches the browser? if you change src to data-src the browser won't load it. Then you can add the loading="lazy" attribute and then change the src to the value of data-src. Commented Nov 3, 2021 at 5:45

2 Answers 2

3

The typical solution to this is to use data-src attributes instead of src. Then, when you're ready, you switch them to src attributes.

That means the images don't get loaded by the browser until you decide.

This is commonly handled by libraries like lazysizes. But here's a general concept:

const images = document.querySelectorAll('img');
images.forEach(img => img.src = img.dataset.src);
<img data-src="https://via.placeholder.com/350x150" loading="lazy">
<img data-src="https://via.placeholder.com/350x350" loading="lazy">

Sign up to request clarification or add additional context in comments.

Comments

2

It's kind of a catch 22. You need to run the JS before the HTML to set the attribute before it is already loading, but you can't add an attribute to an element that doesn't exist.

You could try creating the image element manually using JS, then adding the attribute, then adding it to the dom.

Maybe something like this:

const imgEl = document.createElement("img");
imgEl.src = "https://i.sstatic.net/ZCVxN.jpg?s=64&g=1"
imgEl.setAttribute('loading', 'lazy');

const body = document.querySelector("body")
body.appendChild(imgEl);

3 Comments

That would be a buttload of javascript... especially for hundreds of images.
Would also be a lot of html I guess, wrap it into a function so you have some nice one liners.
Nothing is wrong with html. The question was asking why the JavaScript method behaves as is does. I’m not an expert with SEO so cannot provide accurate info there but I believe the SEO crawlers will allow a page a certain time to load. So if your image loads fast enough then (maybe) it might not have such a negative effect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.