DEV Community

Cover image for How to lazy load images in html with pure Javascript?
HARSH VATS
HARSH VATS

Posted on • Edited on

How to lazy load images in html with pure Javascript?

Let's read this article at my place :)

If you just want to do image lazy loading without any understanding of the concepts involved because maybe this is your first time and you have to use in it your project then don't worry at all. I can assure you this article will give you everything already done so that you just need to copy paste.

1. Copy paste this code just before closing body tag

document.addEventListener('DOMContentLoaded', function () {
        var lazyloadImages = document.querySelectorAll('img.lazy');
        var lazyloadThrottleTimeout;

        function lazyload() {
          if (lazyloadThrottleTimeout) {
            clearTimeout(lazyloadThrottleTimeout);
          }

          lazyloadThrottleTimeout = setTimeout(function () {
            var scrollTop = window.pageYOffset;
            lazyloadImages.forEach(function (img) {
              if (img.offsetTop < window.innerHeight + scrollTop) {
                img.src = img.dataset.src;
                img.classList.remove('lazy');
              }
            });
            if (lazyloadImages.length == 0) {
              document.removeEventListener('scroll', lazyload);
              window.removeEventListener('resize', lazyload);
              window.removeEventListener('orientationChange', lazyload);
            }
          }, 20);
        }

        document.addEventListener('scroll', lazyload);
        window.addEventListener('resize', lazyload);
        window.addEventListener('orientationChange', lazyload);
      });
Enter fullscreen mode Exit fullscreen mode

2. Replace image src attribute with data-src

If you have

<img src="<url>" />

then replace it with

<img data-src="<url>" />

3. This is the last point. Add class="lazy" to all the images you want to lazy load.

Now you are good to go. Thank you for reading this article. I don't write articles for others, I write them for myself so I can use ready made code or revise my concepts. But if it helps you in any way then plz let me know here.

Top comments (9)

Collapse
 
thomasverleye profile image
Thomas Verleye

You could choose to not use javascript and add loading="lazy" to your HTML.

Collapse
 
mfurkankaya profile image
Furkan KAYA

Not supported on all browsers.

Collapse
 
harshvats2000 profile image
HARSH VATS • Edited

Furkan is right. It's not supported in all browsers for example Safari.

Collapse
 
thomasverleye profile image
Thomas Verleye

Yes but it's already supported by 75% of the browsers.

If for some reason your javascript doesn't work/breaks/gets blocked users won't see the image you're presenting here.
You also have to consider the fact that you're adding a scroll event listener, this takes up quiet the CPU speed and will drastically slow your website on older browsers and low end computers/phones.

By adding loading="lazy" you add lazy loading as an progressive enhancement.
Browsers which do not support this will still be able to view your images.

And as I started my first comment I used the words "you could choose", it's not like I stated you "must", I'm just suggesting this is probably a better solution :-)

Thread Thread
 
harshvats2000 profile image
HARSH VATS

Hello Thomas!
Plz take a closer look at the js code again. I took cpu consumption into consideration and that's why have used timeout(20ms) in the event listener.
So that's not much of a problem.
And yes 25% of total population is a huge huge number :)

Thread Thread
 
thomasverleye profile image
Thomas Verleye

As I already stated, I'm just suggesting it :-) As I'm trying to say, it's a progressive enhancement. Your website won't be broken on the 25% which doesn't support loading="lazy". The opposite can be said about JavaScript code that doesn't work, if this code does not work or fails to kick in user won't be able to see your images.

Even with a throttle (timeout) this wil slow up low end devices. I would suggest you use passive listeners.

Also, I have taken a closer look at your code and the forEach function is not supported in IE11 and lower, so IE users won't be able to see the images. I'd suggest you use a basic for loop for this.

Thread Thread
 
mfurkankaya profile image
Furkan KAYA

I think you're right about IE 11 and forEach but it can be handled with transpilers. I'm saying that because of many projects are using. If someone uses these lines of code with vanillajs, people won't see the images on IE11 and lower. If you ask me, lower versions are don't matter anymore but IE11 is still worth. We get 5% of our traffic from IE11.

Thread Thread
 
thomasverleye profile image
Thomas Verleye

Transpilers will indeed resolve this, but not all users will be using transpilers who are reading these blog posts.

Nothing wrong with just writing it as a basic for-loop though, then it's completely vanilla and users can simply copy pasted it.

I took the opportunity to improve the code to:

document.addEventListener('DOMContentLoaded', function () {
    var lazyloadThrottleTimeout;

    function lazyload() {
        if (lazyloadThrottleTimeout) {
            clearTimeout(lazyloadThrottleTimeout);
        }

        var lazyloadImages = document.getElementsByClassName('lazy');
        if (lazyloadImages.length < 1) {
            return;
        }

        lazyloadThrottleTimeout = setTimeout(function () {
            var scrollTop = window.pageYOffset;
            for (var i = 0; i < lazyloadImages.length; i++) {
                if (lazyloadImages[i].offsetTop < window.innerHeight + scrollTop) {
                    lazyloadImages[i].src = lazyloadImages[i].dataset.src;
                    lazyloadImages[i].classList.remove('lazy');
                }
            }
        }, 20);
    }

    document.addEventListener('scroll', lazyload);
    window.addEventListener('resize', lazyload);
    window.addEventListener('orientationChange', lazyload);
});
Enter fullscreen mode Exit fullscreen mode
  • I've added a basic for-loop instead of the forEach.
  • Reselected the Lazy Loading images each time the event occurs. This way it's more performant and can't break less. You have to know that sometimes other scripts will remove one of these images and then your script will throw an error. OR if you have inserted new images which should lazy load a reselect of the images would improve that.
  • I would suggest you don't remove the eventlisteners at all if you'd like to load newly added images. The removal of these listeners in the current script didn't work anyway because the array doesn't remove the images that are already lazy loaded :-)
  • As you can see the throttle is not needed if your array is empty so I have early returned the function so no unnecessary timeout have to run.

That being all said, I still recommend using loading="lazy" for the sake of compatibility ✌️

Collapse
 
drehere profile image
Andrey