ウェブ向けのブラウザレベルの画像遅延読み込み

対応ブラウザ

  • Chrome: 77。
  • Edge: 79。
  • Firefox: 75。
  • Safari: 15.4。

loading 属性を使用すると、カスタムの遅延読み込みコードを記述したり、別の JavaScript ライブラリを使用したりしなくても、画像を遅延読み込みできます。この機能のデモは次のとおりです。

遅延読み込みされた画像は、ユーザーがページをスクロールするときに読み込まれます。

このページでは、ブラウザでの遅延読み込みの実装について詳しく説明します。

ブラウザレベルの遅延読み込みを使用する理由

HTTP Archive によると、画像はほとんどのウェブサイトで最もリクエストされるアセット タイプであり、通常は他のリソースよりも多くの帯域幅を消費します。90 パーセンタイルでは、サイトはパソコンとモバイルで 5 MB を超える画像を送信しています。

以前は、画面外の画像の読み込みを遅らせる方法が 2 つありました。

どちらのオプションでも、デベロッパーは遅延読み込み動作を含めることができます。多くのデベロッパーは、より使いやすい抽象化を提供するためにサードパーティ ライブラリを構築しています。

遅延読み込みはブラウザで直接サポートされているため、外部ライブラリは必要ありません。ブラウザレベルの遅延読み込みでは、クライアントが JavaScript を無効にしても画像の読み込みが機能します。ただし、読み込みが遅延されるのは JavaScript が有効になっている場合のみです。

loading 属性

Chrome では、デバイスのビューポートに対する相対的な位置に応じて、異なる優先度で画像を読み込みます。ビューポートより下の画像は低い優先度で読み込まれますが、ページの読み込み時には引き続き取得されます。

loading 属性を使用すると、画面外画像の読み込みを完全に遅らせることができます。

<img src="image.png" loading="lazy" alt="…" width="200" height="200">

loading 属性でサポートされる値は次のとおりです。

  • lazy: ビューポートから計算された距離に達するまで、リソースの読み込みを遅らせます。
  • eager: ブラウザのデフォルトの読み込み動作。この属性を指定しない場合は、ページ上の場所に関係なく画像が読み込まれます。これはデフォルトですが、明示的な値がない場合、ツールが自動的に loading="lazy" を追加する場合、または明示的に設定されていない場合にリンターに警告が表示される場合は、明示的に設定すると便利です。

loading 属性と取得優先度の関係

eager 値は、画像が画面外にある場合に読み込みを遅らせることなく、通常どおりに画像を読み込むように指示するものです。loading 属性のない別の画像よりも、画像の読み込みが速くなることはありません。

重要な画像(LCP 画像など)の取得優先度を上げるには、fetchpriority="high"取得優先度を使用します。

loading="lazy"fetchpriority="high" を含む画像は、画面外にある間は遅延され、ビューポート内に入ると優先度の高い取得が行われます。ブラウザは通常、その画像を優先度高く読み込むため、この組み合わせは実際には必要ありません。

ビューポートからの距離のしきい値

スクロールしなくてもすぐに表示できる画像はすべて、通常どおり読み込まれます。デバイスのビューポートの下にある画像は、ユーザーがその画像の近くまでスクロールしたときにのみ取得されます。

Chromium の遅延読み込みの実装は、オフスクリーン画像がビューポートに表示される前に取得することで、ユーザーがスクロールした時点で読み込みが完了するように、早期に読み込みが終わるようにしています。

距離のしきい値は、次の要因によって異なります。

有効な接続タイプのデフォルト値は、Chromium ソースで確認できます。これらのさまざまなしきい値をテストするには、DevTools でネットワークをスロットリングします。

データ節約とビューポートからの距離のしきい値を改善

2020 年 7 月に Chrome では、画像の遅延読み込みのビューポートからの距離のしきい値を調整し、デベロッパーの期待に沿うように大幅に改善しました。

高速接続(4G)では、Chrome のビューポートからの距離のしきい値を 3000px から 1250px に引き下げ、低速接続(3G 以下)ではしきい値を 4000px から 2500px に変更しました。この変更により、次の 2 つのメリットが得られます。

  • <img loading=lazy> は、JavaScript 遅延読み込みライブラリで提供される機能に近い動作をします。
  • ビューポートからの距離に関する新しいしきい値でも、ユーザーがスクロールした時点で画像が読み込まれている可能性が高いことを意味します。

あるデモを高速接続(4G)で行った場合、ビューポートからの距離の新旧のしきい値を比較してみましょう。

画像の遅延読み込みのしきい値を改善し、高速接続の場合のビューポートからの距離のしきい値を 3,000 ピクセルから 1,250 ピクセルに短縮しました。 ブラウザレベルの遅延読み込みに使用される古い基準と新しい基準の比較。

新しいしきい値と LazySizes(一般的な JavaScript 遅延読み込みライブラリ)の比較:

同じネットワーク条件で読み込む場合、LazySize では 70 KB でしたが、Chrome では、画像が 90 KB だった場合にビューポートからの距離が新しいしきい値に切り替わりました。
Chrome と LazySizes で遅延読み込みに使用されるしきい値の比較。

画像にディメンション属性を指定します

ブラウザが画像を読み込む際、画像のサイズは明示的に指定されていない限り、すぐにはわかりません。ブラウザがページ上に画像用の十分なスペースを予約し、レイアウトのずれを回避できるように、すべての <img> タグに width 属性と height 属性を追加することをおすすめします。

<img src="image.png" loading="lazy" alt="…" width="200" height="200">

または、インライン スタイルで値を直接指定します。

<img src="image.png" loading="lazy" alt="…" style="height:200px; width:200px;">

ディメンションを設定するベスト プラクティスは、遅延読み込みするかどうかにかかわらず <img> タグに適用されますが、遅延読み込みを行う場合はさらに重要になります。

Chromium の遅延読み込みは、画像が表示されたときにすぐに読み込まれるように実装されていますが、適切なタイミングで読み込まれない可能性もあります。そのような場合、画像に widthheight を指定しないと、累積レイアウト シフトへの影響が大きくなります。画像のサイズを指定できない場合は、画像を遅延読み込みすることでネットワーク リソースを節約できますが、レイアウトのずれが増加するリスクがあります。

ほとんどのシナリオでは、サイズを指定していなくても画像は遅延読み込みされますが、注意すべきエッジケースがいくつかあります。widthheight を指定しないと、画像のサイズはデフォルトで 0×0 ピクセルになります。画像のギャラリーがある場合、各画像がスペースを占有せず、画像が画面外に押し出されないため、ブラウザは最初にすべての画像がビューポート内に収まると判断することがあります。この場合、ブラウザはすべてを読み込むことを決定し、ページの読み込みが遅くなります。

loading が多数の画像を処理する仕組みの例については、こちらのデモをご覧ください。

<picture> 要素を使用して、定義した画像を遅延読み込みすることもできます。

<picture>
  <source media="(min-width: 800px)" srcset="large.jpg 1x, larger.jpg 2x">
  <img src="photo.jpg" loading="lazy">
</picture>

どの <source> 要素から読み込むかはブラウザが決定しますが、必要なのは代替の <img> 要素に loading を追加することだけです。

最初のビューポートに表示される画像を常にエアガード ロードする

ユーザーがページを最初に読み込んだときに表示される画像、特に LCP 画像の場合は、ブラウザのデフォルトの即時読み込みを使用して、すぐに使用できるようにします。詳細については、多すぎる遅延読み込みのパフォーマンスへの影響をご覧ください。

loading=lazy は、最初のビューポートの範囲外の画像にのみ使用します。ブラウザは、ページ上の画像の場所を認識するまで画像を遅延読み込みできないため、読み込みが遅くなります。

<!-- visible in the viewport -->
<img src="product-1.jpg" alt="..." width="200" height="200">
<img src="product-2.jpg" alt="..." width="200" height="200">
<img src="product-3.jpg" alt="..." width="200" height="200">

<!-- offscreen images -->
<img src="product-4.jpg" loading="lazy" alt="..." width="200" height="200">
<img src="product-5.jpg" loading="lazy" alt="..." width="200" height="200">
<img src="product-6.jpg" loading="lazy" alt="..." width="200" height="200">

グレースフル デグラデーション

loading 属性をサポートしていないブラウザでは、この属性は無視されます。遅延読み込みのメリットはありませんが、遅延読み込みを行っても悪影響はありません。

よくある質問

ブラウザレベルの遅延読み込みに関するよくある質問を紹介します。

Chrome で画像を自動的に遅延読み込みできますか?

以前の Chromium では、Android 版 Chrome でライトモードが有効で、loading 属性が指定されていないか loading="auto" に設定されている場合、遅延に適した画像が自動的に遅延読み込みされていました。ただし、ライトモードと loading="auto" は非推奨であり、Chrome で画像の自動遅延読み込みを提供する予定はありません。

画像がビューポートに近づくまで待機する時間を変更できますか?

これらの値はハードコードされており、API で変更することはできません。ただし、ブラウザでさまざまなしきい値の距離と変数をテストするにつれて、今後変更される可能性があります。

CSS の背景画像で loading 属性を使用できますか?

いいえ。<img> タグでのみ使用できます。

loading="lazy" を使用すると、計算された距離内にある画像が、表示されていない場合に読み込まれないようにすることができます。これらの画像は、カルーセルの背後にある場合や、特定の画面サイズでは CSS によって非表示になっている場合があります。たとえば、Chrome、Safari、Firefox では、画像要素または親要素で display: none; スタイルを使用して画像を読み込むことはありません。ただし、opacity:0 スタイル設定など、他の画像非表示手法では、ブラウザは画像を読み込みます。実装が想定どおりに動作することを確認するため、必ず実装を徹底的にテストしてください。

Chrome 121 で、カルーセルなどの水平スクロール画像の動作が変更されました。これらのイベントでは、縦方向のスクロールと同じしきい値が使用されるようになりました。つまり、カルーセルのユースケースでは、画像がビューポートに表示される前に読み込まれます。つまり、画像の読み込みがユーザーの目に触れる可能性は低くなりますが、ダウンロード数は増えます。水平方向の遅延読み込みのデモを使用して、Chrome と Safari と Firefox の動作を比較します。

すでにサードパーティ製のライブラリやスクリプトを使用して画像を遅延読み込みしている場合はどうなりますか?

最新のブラウザには遅延読み込みが完全に組み込まれているため、画像を遅延読み込みするためにサードパーティのライブラリやスクリプトを使用する必要はありません。

loading="lazy" とともにサードパーティ ライブラリを引き続き使用する理由の 1 つは、属性をサポートしていないブラウザにポリフィルを提供する、または遅延読み込みがトリガーされるタイミングをより細かく制御するためです。

遅延読み込みに対応していないブラウザにはどのように対応すればよいですか?

ブラウザレベルの画像遅延読み込みは、すべての主要なブラウザで十分にサポートされています。JavaScript に余分な依存関係を必要としないことから、ほとんどのユースケースで使用することをおすすめします。

ただし、より多くのブラウザをサポートする必要がある場合や、遅延読み込みのしきい値をより細かく制御したい場合は、サードパーティのライブラリを使用してサイト上の画像の遅延読み込みを行うことができます。

loading プロパティを使用すると、ブラウザがこの機能をサポートしているかどうかを検出できます。

if ('loading' in HTMLImageElement.prototype) {
  // supported in browser
} else {
  // fetch polyfill/third-party library
}

たとえば、lazysizes は一般的な JavaScript 遅延読み込みライブラリです。loading 属性のサポートを検出して、loading がサポートされていない場合にのみ、lazysizes をフォールバック ライブラリとして読み込むことができます。この処理は次のように行われます。

  • サポートされていないブラウザで早期読み込みを回避するため、<img src><img data-src> に置き換えます。loading 属性がサポートされている場合は、data-srcsrc に置き換えます。
  • loading がサポートされていない場合は、lazysizes からフォールバック コンテンツを読み込み、lazyload クラスを使用して、遅延読み込みする画像を指定します。
<!-- Let's load this in-viewport image normally -->
<img src="hero.jpg" alt="…">

<!-- Let's lazy-load the rest of these images -->
<img data-src="unicorn.jpg" alt="…" loading="lazy" class="lazyload">
<img data-src="cats.jpg" alt="…" loading="lazy" class="lazyload">
<img data-src="dogs.jpg" alt="…" loading="lazy" class="lazyload">

<script>
  if ('loading' in HTMLImageElement.prototype) {
    const images = document.querySelectorAll('img[loading="lazy"]');
    images.forEach(img => {
      img.src = img.dataset.src;
    });
  } else {
    // Dynamically import the LazySizes library
    const script = document.createElement('script');
    script.src =
      'https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.1.2/lazysizes.min.js';
    document.body.appendChild(script);
  }
</script>

このパターンのデモはこちらをご覧ください。古いブラウザで試して、フォールバックがどのように機能するかを確認してください。

iframe の遅延読み込みはブラウザでもサポートされていますか?

対応ブラウザ

  • Chrome: 77。
  • Edge: 79.
  • Firefox: 121。
  • Safari: 16.4。

<iframe loading=lazy> も標準化されました。これにより、loading 属性を使用して iframe を遅延読み込みできます。詳細については、オフスクリーン iframe を遅延読み込みする時代ですをご覧ください。

ブラウザレベルの遅延読み込みは、ウェブページ上の広告にどのような影響を与えますか?

画像または iframe としてユーザーに表示されるすべての広告は、他の画像や iframe と同様に遅延読み込みされます。

ウェブページを印刷する際、画像はどのように処理されますか?

ページが印刷されると、すべての画像と iframe がすぐに読み込まれます。詳しくは、問題 #875403 をご覧ください。

Lighthouse はブラウザレベルの遅延読み込みを認識しますか?

Lighthouse 6.0 以降では、異なるしきい値を使用できるオフスクリーン画像の遅延読み込みのアプローチが考慮され、オフスクリーン画像の遅延読み込みの監査に合格できるようになりました。

画像を遅延読み込みしてパフォーマンスを改善する

画像の遅延読み込みをブラウザがサポートしている場合、ページのパフォーマンスを大幅に改善できます。

Chrome でこの機能を有効にしたときに、異常な動作は発生していますか?バグを報告してください。