読み込み中...

ページスピード対策としてLazy loading(遅延読み込み)を実装する方法9選

JavaScriptとHTMLで遅延読み込みを実装する10の方法 JS
この記事は約17分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●遅延読み込み(Lazy loading)とは?

皆さんは、Webサイトを開いた時に画像の読み込みに時間がかかったことはありませんか?

特に画像の多いサイトだと、なかなか表示されずイライラしてしまったり、読み込み中のままページを離脱してしまったりすることもあるでしょう。

そんな時に役立つのが、遅延読み込み(Lazy loading)という手法です。

遅延読み込みとは、ページを開いた時に全ての画像を一度に読み込むのではなく、画面に表示される部分の画像だけを読み込む方法のことを指します。

画面外の部分は、ユーザーがスクロールして表示される時になって初めて読み込まれます。

これにより、初期表示の際の読み込み時間を大幅に短縮できるのです。

○遅延読み込みのメリット

ではなぜ、遅延読み込みが有効なのでしょうか。

それは次のようなメリットがあるからです。

まず第一に、初期ロード時間の短縮が挙げられます。

必要な画像だけを最初に読み込むことで、ページの表示が高速化します。

これによりユーザーのストレスが軽減され、離脱率の低下にもつながるでしょう。

第二に、帯域幅の節約です。

画面外の画像はそもそも読み込まれないため、不要なデータ通信が発生しません。

これはユーザーにとってもデータ通信量の節約になりますし、サーバー側の負荷軽減にもなります。

第三に、SEO効果も期待できます。

ページの表示速度は、Googleのランキング要因の一つとされています。

遅延読み込みによるページ高速化は、検索順位の向上にもつながる可能性があるのです。

○遅延読み込みのデメリット

一方で、遅延読み込みにはデメリットもあります。

一つは、ユーザーがスクロールした時に画像の読み込みが間に合わず、一時的に空白が表示されてしまうことです。

これではせっかくの遅延読み込みが台無しになってしまいます。

また、JavaScriptを多用する実装方法だと、JavaScriptが無効化されている環境では遅延読み込みが機能しないこともあります。

さらに、遅延読み込みによって画像の読み込みタイミングがずれるため、コンテンツのレイアウトがずれてしまう(CLS: Cumulative Layout Shift の増加)という問題もあります。

○遅延読み込みができているか確認する方法

では実際に遅延読み込みを実装した場合、それがきちんと機能しているかはどう確認すればよいのでしょうか。

最も簡単なのは、実際にページを表示して画像の読み込み具合を目視で確認する方法です。

ページを開いた時に画面外の画像がすぐには表示されず、スクロールに合わせて現れればOKです。

もう少し厳密に確認したい場合は、開発者ツールのNetworkパネルを使うのが有効です。

ChromeやFirefoxの開発者ツールを開き、Networkパネルで画像の読み込みタイミングを観察します。

ページを開いた直後は画面内の画像しか読み込まれず、スクロールに合わせて他の画像が読み込まれていく様子が確認できるはずです。

では、HTMLでの遅延読み込み実装について解説していきましょう。

●HTMLで遅延読み込みを実装する方法

ブラウザの多くが対応しているloading属性を使うことで、HTMLだけで簡単に遅延読み込みを実装できます。

imgタグやiframeタグ、videoタグなどに、loading=”lazy”を指定するだけ。とてもシンプルですが、非常に強力な手法です。

○loading=”lazy”属性を使う

imgタグにloading=”lazy”を追加するだけで、その画像は遅延読み込みの対象になります。

実は、このloading属性にはもう一つの値があって、”eager”を指定するとその要素は即座に読み込まれます。

でもデフォルト値が”eager”なので、普通は省略されているんですよね。

だから、遅延読み込みをしたい時だけ”lazy”を指定すればOKというわけです。

○サンプルコード1:imgタグにloading=”lazy”を指定

<img src="image1.jpg" loading="lazy" alt="画像1">
<img src="image2.jpg" loading="lazy" alt="画像2">
<img src="image3.jpg" loading="lazy" alt="画像3">

このようにすると、image1.jpg、image2.jpg、image3.jpgの3つの画像が全て遅延読み込みの対象になります。

ブラウザはページの表示に必要な画像だけを最初に読み込み、残りはスクロールに合わせて遅延ロードします。

シンプルですが、効果は絶大。

大量の画像を含むページなんかだと、読み込み時間が一気に短縮されるんです。

○サンプルコード2:iframeタグにloading=”lazy”を指定

画像だけでなく、iframeにも使えます。

<iframe src="https://example.com" loading="lazy"></iframe>

これで、そのiframe内のコンテンツは遅延読み込みされるようになります。

広告やYouTube動画などを埋め込む際に便利ですね。

○サンプルコード3:videoタグにloading=”lazy”を指定

もちろん、videoタグにも使えますよ。

<video src="video.mp4" loading="lazy" controls></video>

大きなサイズの動画なんかを読み込む際には特に効果的です。

ページの表示を待たせることなく、スムーズにコンテンツを見せられるようになります。

では、JavaScriptを使った遅延読み込みの実装方法について解説していきましょう。

●JavaScriptで遅延読み込みを実装する方法

JavaScriptを使えば、よりきめ細やかな制御ができるようになります。

ブラウザのサポート状況に左右されずに、柔軟に遅延読み込みを実装できるのが大きなメリットですね。

中でもIntersection Observerは、遅延読み込みを実現するための強力なAPIです。

これを使えば、ある要素が画面内に入ったかどうかを簡単にチェックできるんです。

○Intersection Observerを使う

具体的なコードを見てみましょう。

○サンプルコード4:Intersection Observerの基本的な使い方

// 遅延読み込みしたい画像に付けるクラス名
const lazyClass = 'lazy';

// 画像を監視するためのIntersection Observerを作成
const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    // 画面内に入った画像に対して処理を行う
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src; // data-src属性から画像パスを取得してsrcに設定
      img.classList.remove(lazyClass); // lazyクラスを削除
      observer.unobserve(img); // 監視を停止
    }
  });
});

// lazyクラスが付いた画像を取得して監視を開始
const lazyImages = document.querySelectorAll(`.${lazyClass}`);
lazyImages.forEach(img => {
  observer.observe(img);
});

まず、遅延読み込みしたい画像に特定のクラス(ここではlazy)を付けておきます。

そして、Intersection Observerを作成し、lazyクラスが付いた画像を監視対象にします。

画像が画面内に入ったら、data-src属性から画像パスを取得してsrcに設定することで、画像の読み込みを開始します。

同時にlazyクラスを外して、監視対象からも外します。

これだけで、画面内に入った画像だけを遅延読み込みできるようになるんです。

○サンプルコード5:複数の画像を遅延読み込み

<img data-src="image1.jpg" class="lazy" alt="画像1">
<img data-src="image2.jpg" class="lazy" alt="画像2">
<img data-src="image3.jpg" class="lazy" alt="画像3">
// 実行結果
// 画面内に入った画像から順次読み込まれる

HTMLでは、srcではなくdata-src属性に画像パスを指定しておきます。

そして、lazyクラスを付けておくことで、JavaScriptから監視対象にできるというわけですね。

実行結果は、画面内に入った画像から順番に読み込まれていきます。

スクロールに合わせて必要な画像だけが読み込まれるので、ページの表示速度が大幅に改善されるんです。

○jQueryのlazyloadプラグインを使う

Intersection Observerを直接使うのは少し面倒だと感じる方もいるかもしれません。

そんな時は、jQueryのlazyloadプラグインを使うのもおすすめです。

○サンプルコード6:jQueryのlazyloadプラグインの使い方

<img data-original="image1.jpg" class="lazy" alt="画像1">
<img data-original="image2.jpg" class="lazy" alt="画像2">
<img data-original="image3.jpg" class="lazy" alt="画像3">
// lazyloadプラグインを適用
$('.lazy').lazyload();
// 実行結果
// 画面内に入った画像から順次読み込まれる

使い方はとてもシンプルです。

遅延読み込みしたい画像にlazyクラスを付け、data-original属性で画像パスを指定します。

そして、JavaScriptでlazyloadプラグインを呼び出すだけ。

あとは自動的に画面内の画像が読み込まれるようになります。

Intersection Observerほど細かな制御はできませんが、手軽に使えるのが魅力ですね。

では、WordPressでの遅延読み込み実装について解説していきましょう。

●WordPressで遅延読み込みを実装する方法

WordPressを使ってサイトを運営している方も多いと思います。

でも大量の画像を使っていると、どうしてもページの表示速度が遅くなってしまいますよね。

そんな時におすすめなのが、WordPress用の遅延読み込みプラグインです。

中でもEWWW Image Optimizerは、画像の最適化と遅延読み込みを同時に実現してくれる優れものです。

○EWWWプラグインを使う

EWWWプラグインの使い方は至ってシンプル。

プラグインをインストール・有効化したら、設定画面から遅延読み込みをONにするだけです。

具体的にはWordPress管理画面の「設定」タブの「EWWW Image Optimizer」をクリック。

その後遅延読み込みを押すだけで自動で遅延読み込みをしてくれます。

※ただ、圧縮率が無料版だと低いので、有料版を購入することを推奨します。

これだけで、自動的に画像の遅延読み込みが適用されます。

●よくあるエラーと対処法

遅延読み込みを実装してみたものの、思ったように動かない…なんてことありませんか?

実は遅延読み込みにはいくつかの落とし穴があって、ちょっとしたミスでエラーに遭遇することがあるんです。

でも大丈夫、ここではそんな典型的なエラーと、その対処法をご紹介します。困った時の助け舟になれば嬉しいです。

○画像が表示されない場合の対処法

まず、画像が表示されないケース。

遅延読み込みを実装したのに、肝心の画像が現れないなんて話ですよね。

よくある原因は、JavaScriptで参照している画像のパスが間違っていること。

HTMLのdata-src属性には正しいパスを指定しているのに、JavaScriptで画像パスを設定する際にミスがあると、画像は表示されません。

その場合の対処法は、JavaScriptコードを見直して、画像パスが正しいかどうかをチェックすること。

ChromeやFirefoxの開発者ツールを使えば、コンソールにエラーメッセージが出ているはずです。

それを手がかりに、コードを修正しましょう。

また、HTMLのdata-src属性自体が間違っている可能性もあります。

こちらも開発者ツールのElementsパネルで、属性値を確認してみてください。

○モバイルで遅延読み込みが効かない場合の対処法

モバイルサイトを表示した時に限って、遅延読み込みが動かないことがあります。

その原因の多くは、モバイルブラウザがIntersection Observerに対応していないから。

でもがっかりしないでください。そんな時はpolyfillを使うのが一般的な対処法です。

polyfillとは、その機能に対応していないブラウザでも、同等の機能を実現してくれるライブラリのこと。

Intersection Observer用のpolyfillを読み込めば、エラーを回避できるんです。

お勧めのpolyfillはGitHubで公開されているintersection-observer.jsです。

CDNからスクリプトを読み込むだけで、簡単に使えますよ。

<script src="https://cdn.jsdelivr.net/npm/intersection-observer@0.12.0/intersection-observer.js"></script>
// 実行結果
モバイルブラウザでもIntersection Observerが使えるようになり、遅延読み込みが動作する

○遅延読み込みによりCLSが増加する場合の対処法

遅延読み込みを実装したら、逆にページのパフォーマンス指標が悪化した…なんてガッカリした経験ありませんか?

特にCLS(Cumulative Layout Shift)の増加は、遅延読み込みあるあるの問題なんです。

CLSとは、ページの読み込み中にコンテンツがガタガタと動いてしまう現象のこと。

遅延読み込みで画像の表示タイミングがずれることが原因で起きやすいんですよね。

その対処法としては、画像の表示領域をあらかじめ確保しておくこと。

具体的には、imgタグにwidth属性とheight属性を指定して、画像のアスペクト比を固定するんです。

<img data-src="image.jpg" width="600" height="400" alt="サンプル画像"> 

こうしておけば、画像が読み込まれる前でも、同じサイズの領域が確保されるので、画像が表示された時のガタつきを防げるんですね。

// 実行結果
画像の表示領域が確保され、遅延読み込みによるレイアウトのズレが解消される

エラー対処、いかがでしたか?

思い当たる節があれば、ぜひ試してみてください。

でも一番大切なのは、エラーメッセージをしっかり読むことです。

●遅延読み込みの応用例

さて、ここまで遅延読み込みの基本的な実装方法を見てきましたが、もっと応用的な使い方もあるんです。

せっかく身につけた知識を、さらに深めていきましょう。

○サンプルコード7:背景画像の遅延読み込み

まずは、背景画像の遅延読み込み。

imgタグだけでなく、背景画像にも使えるんですよ。

.lazy-background {
  background-image: none; /* 初期状態では背景画像を指定しない */
  background-color: #ccc; /* 背景色は仮置きしておく */
}

.lazy-background.loaded {
  background-image: url('background.jpg'); /* JavaScriptで.loadedを付与したら背景画像を表示 */
}
// Intersection Observerで背景画像を遅延読み込み
const lazyBackgrounds = document.querySelectorAll('.lazy-background');
const observerBackground = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('loaded'); // 表示領域に入ったら.loadedを付与
      observerBackground.unobserve(entry.target);
    }
  });
});

lazyBackgrounds.forEach(background => {
  observerBackground.observe(background);
});
// 実行結果
ページ下部の背景画像が遅延読み込みされ、表示が高速化する

CSSでは、初期状態で背景画像を指定せず、仮の背景色だけを設定しておきます。

そして、JavaScriptでIntersection Observerを使って、要素が表示領域に入ったら.loadedクラスを付与。

すると、背景画像がCSSで指定した画像に切り替わる、というわけです。

大きなサイズの背景画像を使う場合に特に有効ですね。

○サンプルコード8:遅延読み込みとPreload/Prefetchの併用

遅延読み込みとは逆に、事前に読み込んでおきたいリソースもあります。

そんな時はPreloadやPrefetchを使うのがおすすめ。

<!-- 重要なJavaScriptファイルをPreload -->
<link rel="preload" href="main.js" as="script">

<!-- 次のページで使う画像をPrefetch -->
<link rel="prefetch" href="next-page-image.jpg">

Preloadは、現在のページで必ず使うリソースを事前に読み込むのに使います。

対してPrefetchは、次のページで使うと予想されるリソースを事前に読み込んでおくのに使うんです。

遅延読み込みと組み合わせることで、本当に必要なリソースだけを優先的に読み込み、そうでないものは後回しにする、メリハリのある読み込み制御が可能になります。

// 実行結果
遅延読み込みとPreload/Prefetchを適切に組み合わせることで、ページの表示速度とリソース管理の最適化を実現

○サンプルコード9:動的に追加される要素の遅延読み込み

最後は、動的に追加される要素への遅延読み込みの適用です。

これまでの例は、HTMLに最初から存在する要素を扱っていましたが、JavaScriptで動的に追加される要素にも遅延読み込みは使えるんです。

// 動的に追加した画像を遅延読み込み
const container = document.getElementById('container');
const newImage = document.createElement('img');
newImage.dataset.src = 'dynamic-image.jpg'; // data-src属性にパスをセット
newImage.classList.add('lazy'); // lazyクラスを付与
container.appendChild(newImage);

// 新しく追加した画像も監視対象に含める
const lazyImages = document.querySelectorAll('img.lazy');
lazyImages.forEach(img => {
  observer.observe(img);
});
// 実行結果
JavaScriptで動的に追加した画像にも遅延読み込みが適用され、表示速度が改善される

コツは、動的に追加する要素にもdata-src属性とlazyクラスを付けておくこと。

そして、追加後にその要素をIntersection Observerの監視対象に含めてあげれば、あとは今まで通り遅延読み込みしてくれます。

まとめ

長い道のりでしたが、遅延読み込みの基礎から応用まで、一通りマスターできたのではないでしょうか。

HTMLやJavaScript、WordPressでの実装方法を押さえ、つまずきがちなエラー対処法も身につけました。

最初は難しく感じるかもしれませんが、コツをつかめばスムーズに実装できるはず。

ページの表示速度改善は、ユーザー体験とSEOに直結する重要な要素。

ぜひ習得した知識を活かして、Webサイトのパフォーマンスを上げる達人を目指してください。

困難に直面しても、トライアンドエラーを恐れずに。

その経験が、エンジニアとしての成長を加速させます。

そして最高のパフォーマンスで、ユーザーとクライアントの期待に応えましょう。