labs-scnm
8/20/2017 - 5:14 PM

Lazy loading images with Intersection Observer

Lazy loading images with Intersection Observer

/** 
 * A simple demo on how the new Intersection Observer API can be used to lazy load images.
 * https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
 *
 * Intersection Observer is available in most modern browsers and there's a decent polyfill, too:
 * https://github.com/WICG/IntersectionObserver/tree/gh-pages/polyfill
 */

let imageNodes = [];

// generate some test image
for ( let i = 0; i < 1000; i++ ) {
    let image = document.createElement( 'img' );
    image.setAttribute( 'data-src', 'https://api.adorable.io/avatars/285/' + i ); // Note: Not using `src` here.
    document.body.appendChild( image );
    imageNodes.push( image );
}

const intersectionObserver = new IntersectionObserver(
    onIntersectionObservation,
    { rootMargin: '0px 0px 1000px 0px' } // preload all images that are in the viewport and 1000px below "the fold".
);
imageNodes.forEach( ( imageNode ) => intersectionObserver.observe( imageNode ) );

function onIntersectionObservation( entries, observer ) {
    entries
        .filter(  ( entry ) => entry.target.hasAttribute( 'data-src' ) && entry.isIntersecting )
        .forEach( ( entry ) => {
            // swap data-src and src
            entry.target.setAttribute( 'src', entry.target.getAttribute( 'data-src' ) );
            entry.target.removeAttribute( 'data-src' );
            observer.unobserve( entry.target );
        } )
    ;
}