Recipe 12.5

Creating a Lazy Loading Image Component

The image will not load until it scrolls into the viewport.

Demo

Lorem Ipsum

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas blandit nunc vitae luctus varius. Quisque nisl purus, accumsan et hendrerit et, ornare sed lectus. Sed risus lacus, consequat ac molestie nec, molestie ac dui. Donec iaculis laoreet leo id molestie. Fusce eu quam ut nisl interdum mollis. Phasellus mollis magna at commodo aliquam. Aenean convallis nibh est, a eleifend sapien eleifend ut. Curabitur tincidunt nisi et tincidunt vehicula. Praesent gravida malesuada odio, vitae condimentum leo rutrum vitae. Praesent euismod sem sed efficitur laoreet. Morbi id nisl enim. Vivamus euismod consectetur eleifend. Aenean congue tellus leo, varius hendrerit justo aliquam a. Donec eu condimentum lorem, ut condimentum magna. Donec aliquam volutpat iaculis.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas blandit nunc vitae luctus varius. Quisque nisl purus, accumsan et hendrerit et, ornare sed lectus. Sed risus lacus, consequat ac molestie nec, molestie ac dui. Donec iaculis laoreet leo id molestie. Fusce eu quam ut nisl interdum mollis. Phasellus mollis magna at commodo aliquam. Aenean convallis nibh est, a eleifend sapien eleifend ut. Curabitur tincidunt nisi et tincidunt vehicula. Praesent gravida malesuada odio, vitae condimentum leo rutrum vitae. Praesent euismod sem sed efficitur laoreet. Morbi id nisl enim. Vivamus euismod consectetur eleifend. Aenean congue tellus leo, varius hendrerit justo aliquam a. Donec eu condimentum lorem, ut condimentum magna. Donec aliquam volutpat iaculis.

Code

JavaScript
class LazyImage extends HTMLElement {
  constructor() {
    super();

    const shadowRoot = this.attachShadow({ mode: 'open' });
    this.image = document.createElement('img');
    shadowRoot.appendChild(this.image);
  }

  connectedCallback() {
    const observer = new IntersectionObserver(entries => {
      if (entries[0].isIntersecting) {
        console.log('Loading image');
        this.image.src = this.getAttribute('src');
        observer.disconnect();
      }
    });

    observer.observe(this);
  }
}

if (!customElements.get('lazy-image')) {
  customElements.define('lazy-image', LazyImage);
}
HTML
<div style="max-height: 20em; overflow: auto;">
  <h2>Lorem Ipsum</h2>
  <p class="fs-5">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas blandit nunc vitae luctus varius. Quisque nisl
    purus, accumsan et hendrerit et, ornare sed lectus. Sed risus lacus, consequat ac molestie nec, molestie ac dui.
    Donec
    iaculis laoreet leo id molestie. Fusce eu quam ut nisl interdum mollis. Phasellus mollis magna at commodo aliquam.
    Aenean convallis nibh est, a eleifend sapien eleifend ut. Curabitur tincidunt nisi et tincidunt vehicula. Praesent
    gravida malesuada odio, vitae condimentum leo rutrum vitae. Praesent euismod sem sed efficitur laoreet. Morbi id
    nisl
    enim. Vivamus euismod consectetur eleifend. Aenean congue tellus leo, varius hendrerit justo aliquam a. Donec eu
    condimentum lorem, ut condimentum magna. Donec aliquam volutpat iaculis.
  </p>

  <p class="fs-5">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas blandit nunc vitae luctus varius. Quisque nisl
    purus, accumsan et hendrerit et, ornare sed lectus. Sed risus lacus, consequat ac molestie nec, molestie ac dui.
    Donec
    iaculis laoreet leo id molestie. Fusce eu quam ut nisl interdum mollis. Phasellus mollis magna at commodo aliquam.
    Aenean convallis nibh est, a eleifend sapien eleifend ut. Curabitur tincidunt nisi et tincidunt vehicula. Praesent
    gravida malesuada odio, vitae condimentum leo rutrum vitae. Praesent euismod sem sed efficitur laoreet. Morbi id
    nisl
    enim. Vivamus euismod consectetur eleifend. Aenean congue tellus leo, varius hendrerit justo aliquam a. Donec eu
    condimentum lorem, ut condimentum magna. Donec aliquam volutpat iaculis.
  </p>

  <lazy-image src="https://placekitten.com/200/138"></lazy-image>
</div>
Web API Cookbook
Joe Attardi