Intersection illustration (with shadow root)

by Julien Roche

HTML

<body class="main">
  
  <section class="main__gallery">
    <template shadowrootmode="open">
      <style>
        .main__gallery__item {
          border: 1px solid black;
          height: 150px;
          margin: 10px 0px 10px 0px;
          width: 150px;
        }
      </style>
      <img class="main__gallery__item" data-src="http://www.petmd.com/sites/default/files/scared-kitten-shutterstock_191443322.jpg">
      <img class="main__gallery__item" data-src="http://www.petmd.com/sites/default/files/scared-kitten-shutterstock_191443322.jpg">
      <img class="main__gallery__item" data-src="http://www.petmd.com/sites/default/files/scared-kitten-shutterstock_191443322.jpg">
      <img class="main__gallery__item" data-src="http://www.petmd.com/sites/default/files/scared-kitten-shutterstock_191443322.jpg">
      <img class="main__gallery__item" data-src="http://www.petmd.com/sites/default/files/scared-kitten-shutterstock_191443322.jpg">
      <img class="main__gallery__item" data-src="http://www.petmd.com/sites/default/files/scared-kitten-shutterstock_191443322.jpg">
    </template>
  </section>
</body>

CSS

html {
  height: 100%;
  width: 100%;
}

.main {
  align-items: center;
  display: flex;
  height: 90vh;
  justify-content: center;
}

.main__gallery {
  border: 2px solid red;
  height: 300px;
  overflow: auto;
  text-align: center;
  width: 300px;
}

JavaScript

'use strict';

function hasDataSrcAttribute(htmlElement) {
	return !!htmlElement.getAttribute('data-src');
}

// Remember the list of images
const images = document.querySelector('.main__gallery').shadowRoot.querySelectorAll('.main__gallery__item');

// Put in place the observation
let observer = new IntersectionObserver(
	entries => {
  	let hasDataSrc = entries.find(entry => hasDataSrcAttribute(entry.target));
    
    if (hasDataSrc) {
    	entries
      	.filter(entry => hasDataSrcAttribute(entry.target))
        .forEach(function (entry) {
        	if (entry.intersectionRatio > 0) {
            // We have to load the image, so no need anymore to observe it
            observer.unobserve(entry.target);
            
            // Load the image
            entry.target.src = entry.target.getAttribute('data-src');
            entry.target.removeAttribute('data-src');
          }
        });
    
    } else {
    	// No need anymore the observer: all the images were loaded
      observer.disconnect();
    }
  },
  {
  	// If the image gets within 50px in the Y axis, start the download.
  	'rootMargin': '50px 0px',
  	'threshold': 0.01
  }
);

// Associated the observer on each images
images.forEach(image => observer.observe(image));