How to implement LazyLoad with a scrollable DIV using the Intersection Observer API?

234 views Asked by At

I am using the LazyLoad library at github.com/tuupola/lazyload which works great if you have the body as the root to detect images that come into the viewport.

However, I have a DIV with fixed width and height, actually covering the entire visible browser window. And I need to have lazyload assigned to this DIV, so when the DIV is scrolled, lazy load loads the images inside this DIV, that are coming into the viewport.

With the LazyLoad library it is possible to pass another root:

new LazyLoad(images, {
     root: document.querySelector('#wrapper'),
});

In my JQuery code I specifically use:

$('img.lazyload').lazyload({
    effect: 'fadeIn',
    root: $('#wrapper'),
});

But it does not work. Neither with root: $('#wrapper')[0],

I also reported this at github/lazyload but maybe it is not a bug with the library, however, has to do with the Intersection Observer API?

3

There are 3 answers

0
libra On

I make an example and it works

https://jsbin.com/koyuquduzu/edit?html,css,js,console,output

$('.lazyload').lazyload({
    root: app
  })

enter image description here

0
Manish On

As of writing this answer lazy loading images is supported by all browsers out of the box, even on android and ios browsers. You do not need to use any third party plugins to achieve the same.

All you need to do is add the attribute loading="lazy" on your img tags just like below:

<img src="imageUri" alt="image" loading="lazy">

Browser support:

browser support

You can find more details here:

MDN lazy loading

web.dev image lazy loading

MDN image loading attribute

0
engrhussainahmad On

Here is a full example of implementing LayLoad with a scrollable div using the Intersection Observer API.

HTML Structure:

<div class="scrollable-container">
    <div class="item">
        <img data-src="image1.jpg" alt="Image 1">
    </div>
    <div class="item">
        <img data-src="image2.jpg" alt="Image 2">
    </div>
    <!-- Add more items as needed -->
</div>

CSS:

.scrollable-container {
    height: 400px; /* Set the desired height */
    overflow-y: auto;
}

JavaScript:

// Function to handle image loading
function lazyLoadImage(target) {
    const image = target.querySelector('img');
    const src = image.getAttribute('data-src');
    if (src) {
        image.src = src;
        image.removeAttribute('data-src');
    }
}

// Create an Intersection Observer
const observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            lazyLoadImage(entry.target);
            observer.unobserve(entry.target);
        }
    });
});

// Get all items to observe
const items = document.querySelectorAll('.item');

// Observe each item
items.forEach(item => {
    observer.observe(item);
});

// Initiating Lazy Load
const initialVisibleItems = document.querySelectorAll('.item:is(:in-viewport)');
initialVisibleItems.forEach(item => {
    lazyLoadImage(item);
});

The :is(:in-viewport) selector is a hypothetical example of how you might select elements initially in the viewport using a CSS selector. In practice, you might need to implement this logic manually based on your specific requirements.