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

組み込みの遅延読み込みがついに登場

ウェブでも画像の遅延読み込みがブラウザレベルでサポートされるようになりました。この動画では、この機能のデモをご覧いただけます。

loading 属性を使用すると、カスタムの遅延読み込みコードを記述したり、別の JavaScript ライブラリを使用したりしなくても、画像を遅延読み込みできます。詳しく見ていきましょう。

ブラウザの互換性

対応ブラウザ

  • 77
  • 79
  • 75
  • 15.4

loading 属性をサポートしていないブラウザは、副作用なしにそのまま無視します。

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

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

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

どちらの方法でも、デベロッパーは遅延読み込み機能を含めることができます。また、多くのデベロッパーが、さらに使いやすい抽象化を提供するサードパーティ ライブラリを構築しています。ただし、遅延読み込みはブラウザが直接サポートしているため、外部ライブラリは必要ありません。ブラウザレベルの遅延読み込みにより、クライアントで JavaScript が無効になっていても、画像の遅延読み込みが機能します。

loading 属性

Chrome では、デバイスのビューポートがどこに配置されているかに応じて、異なる優先度で画像が読み込まれます。ビューポートより下にある画像は低い優先度で読み込まれますが、ページの読み込み時に取得されます。

loading 属性を使用すると、スクロールによってアクセスした画面外画像の読み込みを完全に遅らせることができます。

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

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

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

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

eager 値は、画像を通常どおりに読み込む指示であり、画像が画面外にある場合はそれ以上遅延しません。loading="eager" 属性がない場合、画像が別の画像よりも早く読み込まれるわけではありません。

ブラウザはさまざまなヒューリスティックに基づいてリソースに優先順位を付けます。loading 属性は、画像リソースがキューに追加されたタイミングを指定するものであり、キュー内での優先順位の指定方法ではありません。eager は、デフォルトで使用される通常の積極的キューイング ブラウザを意味するだけです。

重要な画像(LCP 画像など)の取得優先度を上げる場合は、取得の優先度fetchpriority="high" とともに使用する必要があります。

loading="lazy"fetchpriority="high" の画像は、画面外にあるときは遅延し、ほぼビューポート内に収まっているときに高い優先度で取得されます。いずれにせよ、このケースでは高い優先度で取得される可能性が高いため、この組み合わせは実際には必要とせず、使用しないでください。

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

スクロールせずに見える範囲(スクロールせずにすぐに表示できる)にある画像はすべて、通常どおりに読み込まれます。デバイスのビューポートより下の位置にある要素は、ユーザーがその近くでスクロールしたときにのみ取得されます。

Chromium の遅延読み込みの実装では、ユーザーが画面の近くまでスクロールしたときに読み込みを完了できるように、画面外の画像が早い段階で読み込まれるようにします。付近の画像がビューポートに表示される前に取得することで、画像が表示されるようになるまでにすでに読み込まれている可能性を最大限に高めることができます。

JavaScript の遅延読み込みライブラリと比較して、スクロールして表示される画像を取得するためのしきい値は、控えめにとらえることができます。

距離のしきい値は一定ではなく、いくつかの要因によって異なります。

有効な接続タイプの各デフォルト値は、Chromium ソースで確認できます。これらの数値、さらにはビューポートから一定の距離に達したときにのみ取得するアプローチも、Chrome チームによる読み込み開始の判断に関するヒューリスティックの改善に伴い、将来的に変更される可能性があります。

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

2020 年 7 月の時点で、Chrome はデベロッパーの期待に応えるために、画像遅延読み込みのビューポートからの距離のしきい値を揃えるために大幅な改善を行いました。

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

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

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

以前のしきい値と新しいしきい値の比較:

画像遅延読み込みの新しいしきい値と改善されたしきい値。高速接続のビューポートからの距離のしきい値を 3,000 ピクセルから 1,250 ピクセルに引き下げました。

LazySizes(一般的な JS 遅延読み込みライブラリ)と新しいしきい値を比較すると、次のようになります。

同じネットワーク条件で LazySizes が 70 KB で読み込むのに対し、Chrome では 90 KB の画像を読み込む新しいビューポートからの距離のしきい値

Google はウェブ標準コミュニティと協力して、ビューポートからの距離のしきい値に関するアプローチをブラウザごとに適切に調整できるよう取り組んでいます。

画像には寸法属性を含める必要があります

ブラウザは画像を読み込みますが、明示的に指定しない限り、画像のサイズをすぐに把握することはできません。ブラウザがページ上に画像用の十分なスペースを予約できるようにするには、すべての <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> タグに適用されます。遅延読み込みを使用すると、この関連性がより高くなります。最新のブラウザでは、画像に widthheight を設定すると、ブラウザでもその固有のサイズを推測できます。

ディメンションが含まれていない場合、ほとんどのシナリオで画像の読み込みが遅延しますが、注意が必要なエッジケースがいくつかあります。widthheight が指定されていない場合、画像のサイズは、最初は 0x0 ピクセルです。このような画像のギャラリーがある場合、各画像は実質的にスペースを占有せず、画像が画面外に押し出されないため、最初はすべての画像がビューポート内に収まっているとブラウザが判断する可能性があります。この場合、ブラウザはすべてがユーザーに表示されていると判断し、すべてを読み込みます。

また、画像サイズを指定すると、レイアウト シフトが発生する可能性が低くなります。画像のサイズを指定できない場合、遅延読み込みを行うと、ネットワーク リソースを節約できる一方で、レイアウト シフトのリスクが高まる可能性があります。

Chromium の遅延読み込みは、画像が表示されるとすぐに読み込まれるように実装されていますが、画像がまだ読み込まれていない可能性が残ります。この場合、そのような画像に width 属性と height 属性がないと、Cumulative Layout Shift への影響が大きくなります。

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

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

どの <source> 要素から読み込むかはブラウザが決定しますが、loading 属性は代替の <img> 要素に含めるだけで済みます。

最初に表示されるビューポートにある画像の遅延読み込みを避ける

最初に表示されるビューポートにある画像には loading=lazy を設定しないでください。これは特に LCP の画像に関係します。詳しくは、遅延読み込みが多すぎる場合のパフォーマンスへの影響をご覧ください。

可能であれば、スクロールしなければ見えない位置にある画像にのみ loading=lazy を追加することをおすすめします。積極的に読み込まれる画像はすぐに取得できますが、遅延的に読み込まれる画像については現在、ブラウザはページ上の画像の場所を把握するまで待つ必要があります。そのため、利用可能にするには IntersectionObserver が必要です。

一般に、ビューポート内の画像はブラウザのデフォルトを使用して積極的に読み込む必要があります。ビューポート内の画像の場合は、loading=eager を指定する必要はありません。

<!-- 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 で画像を自動的に遅延読み込みする予定はありますか?

これまで、ライトモードが Chrome for Android で有効になっていて、loading 属性が指定されていないか loading="auto" に設定されている場合、遅延に適した画像は自動的に遅延読み込みされていました。ただし、(非標準の loading="auto" と同様に)ライトモードは非推奨になりました。現時点では、Chrome で画像を自動的に遅延読み込みする予定はありません。

画像の読み込みを開始する基準となる画像の距離を変更できますか?

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

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

いいえ。現在のところ、<img> タグでのみ使用できます。

デバイスのビューポート内にある画像の遅延読み込みにマイナス面はありますか?

スクロールせずに見える範囲の画像には loading=lazy を配置しないほうが安全です。Chrome では loading=lazy の画像をプリロード スキャナにプリロードせず、また、すべてのレイアウトが完了するまで画像の取得が遅れるからです。詳しくは、最初に表示されるビューポートの画像の遅延読み込みを避けるをご覧ください。

loading="lazy" を使用すると、表示されていない場合でも calculated-distance の範囲内にある場合は、読み込まれないことがあります。たとえば、Chrome、Safari、Firefox では、display: none; スタイル(画像要素または親要素)を使用して画像が読み込まれることはありません。ただし、opacity:0 スタイル設定など、画像を非表示にする方法では、引き続き画像が読み込まれます。実装が常に入念にテストされ、意図したとおりに機能していることを確認してください。

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

最新のブラウザでネイティブ遅延読み込みを完全にサポートできるようになったため、画像の遅延読み込みにサードパーティのライブラリやスクリプトが引き続き必要かどうかを再検討することをおすすめします。

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

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

ポリフィルを作成するか、サードパーティ ライブラリを使用して、サイトで画像を遅延読み込みします。loading プロパティを使用すると、この機能がブラウザでサポートされているかどうかを確認できます。

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

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

  • サポートされていないブラウザでの積極的読み込みを回避するために、<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 の遅延読み込みはブラウザでもサポートされていますか?

対応ブラウザ

  • 77
  • 79
  • 121
  • 16.4

<iframe loading=lazy> も標準化されており、Chromium と Safari にはすでに実装されています。これにより、loading 属性を使用して iframe を遅延読み込みできます。詳しくは、iframe の遅延読み込みに関する専用記事をご覧ください。

ブラウザレベルの遅延読み込みがウェブページ上の広告に与える影響

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

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

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

Lighthouse では、ブラウザレベルの遅延読み込みは認識されますか?

Lighthouse 6.0 以降では、異なるしきい値を使用する可能性のある画面外画像の遅延読み込みのアプローチが考慮され、画面外画像の遅延読み込みの監査に合格しています。

おわりに

画像の遅延読み込みをサポートすることで、ウェブページのパフォーマンスを大幅に向上させることができます。

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