Ownedmedia ウェブ制作に役立つコンテンツを発信中!

JavaScript 2020.12.05

JavaScriptでスクロールに対応した遅延読み込みを作成してみる

Tags: ,

近年のウェブサイトでは表示速度を上げるために、画像が多く用いられている場合に「遅延読み込み」というものが行われている場合があります。通常、ページの読み込み時に合わせてページ内にある各リソースも読み込みが開始するのですが、画像が多かったり、データサイズが大きい場合にはその分初回読み込みの負荷が強くなります。そんな時には画面内に入った時、つまり画像の表示が必要になったタイミングで画像リソースの読み込みが個別の行われるようにすることで、読み込み時間の圧縮と表示最適化が実現できるようになります。

 

そこで今回はJavaScriptを使ってスクロールに合わせて画像リソースの遅延読み込みができるように実装してみたいと思います。この画像リソースの方法ですが、ブラウザのネイティブ機能に対応した属性で指定する方法や、JavaScriptのプラグインを利用する方法、そして自前で1から機能を作成する方法がなどがあります。同じ遅延読み込みの機能でも実装方法が少し異なるので注意が必要です。

 

遅延読み込みの流れですが、基本的にはカスタムデータ属性に画像のパスを値として指定しておき、画面内に要素が入ったタイミングでその値をsrc属性に代入するようにすることで読み込みが遅延して発生するという理屈になります。それでは実際の実装方法を見ていきます。

 

loading属性で実装するパターン

まずは最もシンプルな方法で、HTMLの「loading属性」を使う方法です。これはブラウザのネイティブ機能を利用する形で「loading=”lazy”」と指定しておけば、ブラウザ側で適切なタイミングで遅延読み込みが行われるというものです。指定する際には合わせて画像の幅と高さの値を設定しておきます。

【HTML】※一部抜粋

<img src="./hoge.jpg" loading="lazy" width="400" height="300" ..... alt="">

 

メリットとしては簡単に実装できることです。また、loading属性には値を変えることで遅延読み込みに対応させるかどうかを要素単位で切り分けることができます。ただし現時点では対応しているブラウザが限定的ということで、実際に十分使えるようになるまではもう少し時間がかかりそうですね。実際のサンプルはこちらで確認することができます。

 

プラグイン(lazyload)を使って実装するパターン

続いて、遅延読み込み用のプラグインを使う方法です。使い方については各プラグインによって異なるのですが、今回は「lazyload」という比較的ポピュラーなプラグインを使う例を見ていきます。

【lazyload】
https://github.com/tuupola/lazyload

 

まず対象となる要素に「class=”lazyload”」を指定し、src属性を「data-src」に変更します。そして先ほどと同じく画像の幅と高さの値を設定しておきます。これはCSSでそれに相当するプロパティでの対応でもOKのようです。あとはプラグインのソースコードを読み込んでから、「lazyload();」でイニシャライズ用の関数を実行するだけでOKです。

【HTML】※一部抜粋

<img class="lazyload" data-src="./hoge.jpg" width="400" height="300" ..... alt="">

<script src="https://cdn.jsdelivr.net/npm/lazyload@2.0.0-rc.2/lazyload.js"></script>
<script>
  lazyload();
</script>

 

こちらは先ほどのloading属性を使う方法とは異なり、すべてのブラウザに対応しているので環境を選びません。そしてプラグインということで実装コストもそんなに高くありません。ただしプラグインに依存する形となるので、カスタマイズがやり難かったりする点が気になるところですね。実際のサンプルはこちらで確認することができます。

 

JavaScriptのIntersectionObserverを使って実装するパターン

最後はネイティブのJavaScriptにある「IntersectionObserverAPI」と併用し、動的にsrc属性の値を書き換えることで実装する方法です。IntersectionObserverについては過去記事「JavaScriptのIntersectionObserverAPIでビューポート内での表示を検知する」でも紹介していますが、ビューポート内に要素が入ったかどうかを検知できるというものです。これを使ってスクロールに対応させて要素が画面内に入ると、src属性を書き換える処理を実行することで遅延読み込みが実現できます。

 

具体的には下記のようになります。まずは対象となる要素にトリガーとなるclass名をあてておき、カスタムデータ属性に画像パスを入れておきます。そしてsrc属性は空にしておくことで初回ロードを防ぐようにします。

【HTML】※一部抜粋

<img class="lazy_loading" src="" data-lazy="./hoge.jpg" ..... alt="">

<script>
  const doObserve = (element) => {
    const targets = document.querySelectorAll(element);
    const options = {
      root: null,
      rootMargin: '50px 0px 100px 0px',
      threshold: 0
    }
    const observer = new IntersectionObserver((items) => {
      items.forEach((item, index) => {
        if (item.isIntersecting) {
          if (item.target.classList.contains('lazy_loading') && !item.target.getAttribute('src')) {
            const srcUrl = item.target.getAttribute('data-lazy');
            item.target.setAttribute('src', srcUrl);
          }
        }
      });
    }, options);
    Array.from(targets).forEach((target) => {
      observer.observe(target);
    });
  }
  doObserve('.lazy_loading');
</script>

 

続いてスクリプト側で、IntersectionObserverを使ってビューポート内での要素の表示を検知します。ビューポートに入った時にトリガー用のclass名があり、かつsrc属性の値が空の場合にだけ、カスタムデータ属性で持たせた値をsrc属性にセットさせるようにします。これで遅延読み込みが行われるようになります。こちらは前の2つに比べると実装コストは最も高いですが、より柔軟なカスタマイズができるようになります。例として遅延読み込み実行時にアニメーション効果などを合わせることも可能です。実際のサンプルはこちらで確認することができます。

 


 

今回は、JavaScriptでスクロールに対応した遅延読み込みを実装する方法をまとめてみました。最近ではモバイル端末の普及に合わせてサイトの表示高速化のニーズが高まってきています。画像リソースが多くなる場合にはそれに比例して読み込みに時間がかかる可能性も高くなります。そんな時には遅延読み込みがとても効果的ですので、一度試してみるのもいいのではないでしょうか。

この記事を書いた人

オガワ シンヤ

DesignSupply.代表 / ディレクター・ウェブデザイナー・フロントエンドエンジニアをやっています。「ウェブとデザインでヒト・モノ・サービスを繋げ新しい価値を生み出す」をコンセプトに日々奮闘中!制作中はチョコレートが欠かせない三十路Webクリエイター。

  • Twitter

コメントフォーム

記事に関するご質問やご意見などありましたら下記のコメントフォームよりお気軽に投稿ください。なおメールアドレスは公開されませんのでご安心ください。

内容に問題なければ、お名前・ハンドルネームとメールアドレスを入力いただき、下記の「コメントを送信」ボタンを押してください。

CAPTCHA


この記事もよく読まれています

Scroll to Top
ご質問・ご相談はありませんか ?