こんにちは、ノベルティの山本です。
以前、スクロールアクションを多用してサイトを制作していたらIEとEdgeで不具合が沢山おこり嫌な思いをしたので、Intersection Observer APIを使用してにコードを書き直しました。
Intersection Observer APIはとても便利なので、この記事を書いて共有しようと思います。
近いうちにコードの解説も追記しようと思いますが、まずは使えるだけで良いかなと思ったので、コピペで使える画像遅延読み込みを書いてみました。
画像遅延読み込みだけでなく、他のことにも転用することが可能なのでアレンジしてみてください。

Intersection Observer(インターセクション オブザーバー)とは?

対象要素が画面の表示範囲に入ってから、何かアクションをさせたい時にIntersection Observer APIを使うと便利です。
Intersectionは交差点、Observerは監視という意味です。意味を繋げると交差を監視するということになります。
つまり、スクロールを監視してイベントを発火させるわけではないので、ブラウザの負担がかなり軽減されるというわけです。

モダンブラウザでは、$(window).on('scroll', function() {の様なスクロール監視ベースのアクションを乱用してもある程度処理してくれますが、IEやEdgeは全くもってスムーズに動いてくれなくなってしまいます。
はじめは、なんでIEやEdgeが重くなっているのかよくわかりませんでしたが、突き詰めると大抵スクロールアクションでした。
なので、そういった事態に出くわしたらIntersection Observer APIを使用すると良いと思います。

他にもIntersection Observer APIの有名な使用例を上げておきます。
Intersection Observerは画像の遅延読み込みを簡単に実装できます。
画像の遅延読み込みをするとサイトの読み込み速度も上がるため、SEO的にもユーザビリティ的にも望ましいでしょう。
すでに、たくさんのサンプルコードがあるので、調べたらすぐに出てきます。

Intersection Observer(インターセクション オブザーバー)の使い方

今回は、画像の遅延読み込みのコードをベースにしてサンプルコードを書きたいと思います。
一回しか呼び出さないので、即時関数で書いた方が綺麗な上に遅延読み込みの使い方に即していると思うのですが、名前をつけたいので普通の書き方をしています。
とりあえず、下記コードをjsファイルにコピペしてhtmlのimgタグにclass="lazyload"をセットすることで第一段階の準備は完了です。

function lazyload() {
    let lazyImages = [].slice.call(document.querySelectorAll("img.lazyload"));
    const options = {
        root: null,
        rootMargin: '300px 0px',
        threshold: [0.25, 0.5]
    }
    if ("IntersectionObserver" in window) {
        const lazyImageObserver = new IntersectionObserver(function(entries, observer) {
            entries.forEach(function(entry) {
                if (entry.isIntersecting) {
                    let lazyImage = entry.target;
                    if (lazyImage.dataset.hasOwnProperty('src')) {
                        lazyImage.src = lazyImage.dataset.src;
                        lazyImage.dataset.src = '';
                        delete lazyImage.dataset.src;
                    }
                    if (lazyImage.dataset.hasOwnProperty('srcset')) {
                        lazyImage.srcset = lazyImage.dataset.srcset;
                        lazyImage.dataset.srcset = '';
                        delete lazyImage.dataset.srcset;
                    }
                    lazyImage.classList.remove("lazyload");
                    lazyImageObserver.unobserve(lazyImage);
                }
            });
        }, options);
        lazyImages.forEach(function(lazyImage) {
            lazyImageObserver.observe(lazyImage);
        });
    } else {
    }
}
.addEventListener("DOMContentLoaded", function() {
    lazyload();
});

第二段階は下記コードの様に、imgタグにダミーの画像を最初に読み込む様に設定して、data-srcに本来読み込ませたいurlを指定します。
はじめに読み込ませているsrcは、1×1pxの最小単位gif画像です。確か一番軽い画像だったと思います。

<img
  class="lazyload"
  src="data:image/gif;base64,R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7"
  data-src="images/hogehoge.jpg"
  alt=""
/>             

以上のコードで動くと思います。
optionsのrootMargin箇所で、イベントを発火させる位置を調整することができます。
cssを指定する様に調整できます。

{ rootMargin: '100px 0px' } //上下100px、左右0px
PAGE TOP