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

対応ブラウザ

  • 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)でのデモの 1 つについて、ビューポートからの距離のしきい値の旧基準と新基準を以下に示します。

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

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

同じネットワーク条件で、Chrome の新しいビューポートからの距離のしきい値で 90 KB の画像を読み込むと、LazySizes では 70 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> 要素から読み込む画像をブラウザが決定しますが、loading はフォールバック <img> 要素にのみ追加する必要があります。

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

ユーザーがページを最初に読み込んだときに表示される画像、特に 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 がサポートされていない場合は、遅延サイズからフォールバックを読み込み、遅延読み込みを開始します。その際、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 でこの機能を有効にしたことで、通常とは異なる動作は検出されますか?バグを報告してください。