4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

画像遅延読み込み(loading属性 + IntersectionObserver)

Last updated at Posted at 2021-02-22

はじめに

担当しているサイトがIE非対応になったため、それとともにパフォーマンス改善処理を見直し画像遅延読み込みが改善の余地があったため今回loading属性+InterSectionObeserverで実装した。

loading属性

Chrome 75からサポート。
loading属性とはブラウザがネイティブで遅延ロードをサポートするもの(参照: https://coliss.com/articles/build-websites/operation/work/native-image-lazy-loading.html)

IntersectionObserver

Intersection Observer APIは直訳すると交差監視APIという名前です。これは要素と要素の交差を検知するAPIになります。(参照: https://ics.media/entry/190902/)

実装

本来、loading属性はHTMLのみで完結しますが、対応ブラウザはChrome 76Firefox 75Chromium 版 Edge においては、デフォルトで利用可能になっていますがそれ以外が使用不可なので使用できない箇所はJavascriptで実装していきます。

HTML

<img class="hoge" src="/images/common/noimage.png" data-src="/images/hoge.png" alt="hoge" loading="lazy">

src="/images/common/noimage.png": 遅延読み込み前に読み込む1×1画像
data-src="/images/hoge.png":読み込む画像(今回はJavaScriptでも使用する可能性があるため、data-srcで指定)
loading="lazy": loading属性セット

JavaScript

const lazyLoad = function () {
  const dataSrc = document.querySelectorAll("img[data-src]")
  const sources = document.querySelectorAll("source[data-srcset]");
  //対応ブラウザかチェック
  if ("loading" in HTMLImageElement.prototype) {
  //loading属性対応の場合 data-srcの値をsrcへセット
    if (sources.length !== 0) {
      sources.forEach(function (source) {
        source.srcset = source.dataset.srcset;
      });
    }
    dataSrc.forEach(function (img) {
      img.src = img.dataset.src;
    });
  } else {
    //loading属性非対応の場合 IntersectionObserverを行う。
    const targets = Array.from(dataSrc);
    const img_path = "data-src";
    const options = {
      // 上下100px手前で発火
      rootMargin: "100px 0px"
    };

    // 初期化
    const observer = new IntersectionObserver(callback, options);

    targets.forEach(function (img) {
      // 監視の開始
      observer.observe(img);
    });

    // コールバック
    function callback(entries, object) {
      entries.forEach(function (entry) {
        // 交差していない
        if (!entry.isIntersecting) return;

        // ターゲット要素
        const img = entry.target;

        // 遅延ロード実行
        loading(img);

        // 監視の解除
        object.unobserve(img);
      });
    }

    // 遅延ロード
    const loading = (img) => {
      // data-srcの値を取得
      if (sources.length !== 0) {
        sources.forEach(function (source) {
          source.srcset = source.dataset.srcset;
        });
      }
      const src_val = img.getAttribute(img_path);
      if (src_val) {
        // 画像パスを設定
        img.src = src_val;
        img.onload = function () {
          // data-src属性を削除
          this.removeAttribute(img_path);
        };
      }
    };
  }
}

const _lazyload = lazyLoad();

export default _lazyload;


"loading" in HTMLImageElement.prototypeで対応ブラウザだとtrueが返される。
IntersctionObserverの処理は別記事で紹介しているので割愛。

おわり

loading属性での遅延読み込みがとにかく記述が少なく、HTMLで完結してくれるから楽。
対応ブラウザが今後も増えてくれることを願います。

参照記事

ics.media JSでのスクロール連動エフェクトには
Chromeに実装される新機能『loading属性』について解説、ついにブラウザがネイティブで遅延ロードをサポート

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?