ジャンルから探す

Web Design English

loading=”lazy”が効かない原因とデメリット|HTMLの正しい書き方

loading="lazy" を書いたのに遅延読み込みされないとき、原因は対応していない要素に書いている・属性を書き忘れている・遅延させてはいけない画像に書いているのどれかで切り分けられます。<img> と <iframe> に書く限り、2026年時点で全モダンブラウザが対応済み(Baseline)なので、ブラウザ側の未対応を疑う必要はまずありません。

この記事では、効く範囲と効かない範囲をはっきり分けて整理し、あわせて loading="lazy" のデメリット(読み込みが始まる距離を調整できない、演出や計測には使えない)と、fetchpriority / decoding との組み合わせ方まで解説します。

スポンサーリンク

loading=”lazy” が効くのは img と iframe だけ

結論から言うと、loading 属性が使えるのは <img> と <iframe> の2つだけです。値は lazy と eager(既定)の2つです。

<img src="photo.jpg" width="800" height="600" alt="サンプル画像" loading="lazy">

<iframe src="https://www.google.com/maps/embed?pb=..." width="600" height="400"
        loading="lazy" title="店舗の地図"></iframe>
要素 loading属性 代わりに使うもの
<img> ✅ 使える —
<iframe> ✅ 使える —
<video> ❌ 使えない preload="none" と poster
<source> ❌ 使えない 親の <img> 側に書く
CSSの背景画像 ❌ 使えない Intersection Observer
<script> ❌ 使えない defer / async / 動的import()

<picture> を使う場合は、<source> ではなく中の <img> に loading="lazy" を書きます。判定はあくまで <img> が行うためです。<source> 側に書いても無視されるので、ここは効かない原因として真っ先に確認したい場所です。

<picture>
  <source srcset="photo.avif" type="image/avif">
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" width="800" height="600" alt="サンプル画像" loading="lazy">
</picture>

「ブラウザが自動で lazy にしてくれる」は誤りです

属性を書かなければ遅延読み込みは起きません。 既定値は eager(すぐ読み込む)です。

この誤解には出どころがあります。Chrome は2019年に、Android の Lite モード(データセーバー)利用時に画面外の画像とiframeを自動で遅延読み込みする機能を入れていました。loading="auto" という値もありました。

しかしLite モードと loading="auto" はどちらも廃止済みで、Chrome は自動で遅延読み込みする予定は無いと明言しています。したがって2026年時点では、開発者が明示的に loading="lazy" を書く以外の道はありません。

同様に、<video> や <source> に loading 属性が追加された事実もありません。動画を後回しにしたい場合は次のように書きます。

<video src="movie.mp4" poster="thumbnail.jpg"
       width="640" height="360" controls preload="none"></video>

preload="none" で動画本体の取得を止め、poster で軽い静止画だけ先に見せる。これが動画版の遅延読み込みです。

スポンサーリンク

width と height を書かないとレイアウトが飛ぶ

書かないとレイアウトシフト(CLS)が起きます。 読み込み前の画像の高さは0なので、画像が届いた瞬間に下のコンテンツが押し下げられます。遅延読み込み自体は効いているのに「表示が崩れる」と見える場合は、ここが原因です。

<!-- ✅ 領域が先に確保される -->
<img src="photo.jpg" width="800" height="600" alt="サンプル画像" loading="lazy">

<!-- ❌ 画像が届いた瞬間に本文が飛ぶ -->
<img src="photo.jpg" alt="サンプル画像" loading="lazy">

レスポンシブで幅を可変にしたい場合も、HTML属性には実寸を書いたうえでCSSで調整します。ブラウザはwidthとheightからアスペクト比を計算して領域を確保するので、これが最も確実です。

img {
  max-width: 100%;
  height: auto;
}

ファーストビューの画像に lazy を付けてはいけない

LCP(Largest Contentful Paint)が確実に悪化します。 ページ上部のメイン画像に loading="lazy" を付けると、ブラウザはレイアウトが確定するまで取得を始めません。最大要素の描画が数百ミリ秒〜数秒遅れます。

ファーストビューの主役画像には、むしろ優先度を上げる指定を入れます。

<!-- ページ最上部のメインビジュアル -->
<img src="hero.jpg" width="1200" height="630" alt="メインビジュアル"
     fetchpriority="high" decoding="async">
属性 役割 使いどころ
loading="lazy" 取得を後回しにする スクロールしないと見えない画像
fetchpriority="high" 取得の優先度を上げる LCPになるメインビジュアル
fetchpriority="low" 取得の優先度を下げる 装飾画像、下部のバナー
decoding="async" デコードでメインスレッドを止めない 基本的に全ての画像

判断基準は「スクロールせずに見えるか」の一点です。WordPressのプラグインなどで全画像に一括で loading="lazy" を付ける設定を使っている場合は、先頭の画像を除外できるか必ず確認してください。ここを外すだけでLCPが目に見えて改善することがあります。

スポンサーリンク

loading=”lazy” のデメリットと限界

属性1つで済む手軽さの代わりに、細かい制御が一切できません。デメリットとして挙がるのは、ほぼ次の2点です。

読み込みが始まる距離は調整できない

ブラウザはビューポートから一定距離手前で取得を開始します。この距離は固定値ではなく、実効的な回線速度によって変わります。Chrome は高速回線では短く、低速回線では長めに取る実装になっています。

つまり、開発者がしきい値を調整することはできません。「もっと早く読み込ませたい」という要件があるなら、選択肢は次のどちらかです。

  • そもそも loading="lazy" を付けない(=重要な画像である)
  • Intersection Observer で rootMargin を自分で指定する

背景画像・演出・計測には使えない

loading 属性は「画面に近づいたら取得する」だけの機能です。次のことはできません。

  • CSSの背景画像の遅延読み込み:属性を書く場所がありません
  • 読み込み完了に合わせたフェード演出:別途loadイベントでクラスを付ける必要があります
  • 要素が画面に入った回数の計測
  • 広告や地図スクリプトを表示直前に初期化する

これらの実装と、rootMargin での先読みはIntersection Observerで背景画像と埋め込みを遅延読み込みする方法にまとめています。

効いているかを確かめる方法

入れっぱなしにせず、必ず前後を測ってください。見るべき指標は次の3つです。

  • LCP:主役画像を lazy にしていないか。悪化したら真っ先に疑う
  • CLS:width/height の書き忘れが無いか
  • 転送量:DevTools の Network タブで、初期表示時の画像リクエスト数が減っているか

「属性を書いたのに効いていない」ことを確かめたいときは、DevTools の Network タブを開いたままページ上部だけを表示し、画面外の画像のリクエストが飛んでいないかを見るのが手早いです。飛んでいれば、属性が届いていない(<source> 側に書いた、ビルドで消えている、など)と判断できます。

Lighthouse は「Defer offscreen images」と「Largest Contentful Paint image was lazily loaded」の両方を指摘してくれるので、この2つが同時に出ていないかを確認するのが手早いです。

まとめ

  • loading 属性が効くのは <img> と <iframe> だけ。<video>や<source>には無い
  • <picture> では <source> ではなく中の <img> に書く
  • 既定は eager。書かなければ遅延読み込みは起きない(自動でlazyになるブラウザは無い)
  • loading="auto" と Chrome の Lite モード自動遅延は廃止済み
  • width と height を必ず書いてCLSを防ぐ
  • ファーストビューの画像に lazy を付けない。むしろ fetchpriority="high"
  • デメリットは読み込み開始距離を調整できないこと、背景画像・演出・計測には使えないこと。そこは Intersection Observer の担当

属性2つで済む話ですが、「どの画像に付けないか」の判断の方が効果に効きます。まずはページ先頭の画像から見直してみてください。