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

Browser Support

  • 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 のソースで確認できます。 これらのしきい値は、 デベロッパー ツールでネットワークをスロットリングして テストできます。

データ使用量の削減とビューポートからの距離のしきい値の改善

2020 年 7 月に、Chrome はビューポートからの距離のしきい値を大幅に改善し、デベロッパーの期待に応えるようにしました。

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

  • <img loading=lazy> は、JavaScript の遅延読み込みライブラリが提供するエクスペリエンスに近い動作になります。
  • ビューポートからの距離のしきい値が新しくなったことで、ユーザーがスクロールしたときに画像が読み込まれている可能性が高くなります。

高速接続(4G)でのデモの 1 つで、ビューポートからの距離のしきい値の新旧を比較した結果を次に示します。

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

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

同じネットワーク条件で 90 KB の画像を読み込む Chrome と 70 KB の画像を読み込む LazySizes の、ビューポートからの距離の新しいしきい値。
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 を指定しないと、Cumulative Layout Shift への影響が大きくなります。画像のサイズを指定できない場合は、遅延読み込みを行うことで、レイアウトのずれが増えるリスクを負いながらネットワーク リソースを節約できます。

ほとんどの場合、サイズを指定しなくても画像は遅延読み込みされますが、注意すべきエッジケースがいくつかあります。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 で画像を自動的に遅延読み込みできますか?

以前は、Android 版 Chrome で ライトモード が有効になっていて、loading 属性が指定されていないか loading="auto" に設定されている場合、Chromium は遅延に適した画像を自動的に遅延読み込みしていました。ただし、 ライトモードと 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 の遅延読み込みもブラウザでサポートされていますか?

Browser Support

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

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

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

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

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

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

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

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

画像を遅延読み込みしてパフォーマンスを向上させる

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

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