Claude Codeで画像の遅延読み込みを安全に実装する: Lazy Loading入門
Claude Codeで画像遅延読み込みを実装。LCP、CLS、srcset、失敗例、計測まで初心者向けに解説。
画像の遅延読み込みは、loading="lazy"を付ければ終わりではありません。ファーストビューのヒーロー画像まで遅らせると、Largest Contentful Paint、つまり読者が主要コンテンツを見られるまでの時間が悪化します。逆に、下の方にある一覧画像や関連記事画像を全部先読みすると、スマホ回線では本文が表示される前に帯域を使い切ります。
この記事では、Claude Codeに任せても壊れにくい画像遅延読み込みの型を、HTML、CSS、React、IntersectionObserver、計測、プロンプトまで一通り整理します。判断の基準は、MDNのimg要素、Intersection Observer API、web.devのブラウザネイティブLazy Loading、Core Web Vitals、ChromeのLCP request discoveryを確認した内容です。
画像全体の圧縮や形式変換から見直したい場合はClaude Codeで画像最適化、骨組み表示はスケルトンローディング、サイト全体の速度改善はパフォーマンス最適化も合わせて読むとつながります。
まず結論
基本方針はシンプルです。最初に見える画像は遅延しない。スクロールしないと見えない画像だけを遅延する。どちらの場合もwidthとheight、または同等のaspect-ratioで表示領域を先に確保します。
| 場所 | loading | fetchpriority | decoding | 必須の対策 |
|---|---|---|---|---|
| ヒーロー画像、LCP候補 | eagerまたは省略 | highを検討 | syncまたはasync | HTMLからすぐ発見できる形にする |
| 記事中盤の図解 | lazy | auto | async | widthとheightを入れる |
| 商品一覧の2画面目以降 | lazy | auto | async | srcsetとsizesで小さい画像を選ばせる |
| カルーセルや無限スクロール | 状況次第 | auto | async | IntersectionObserverで少し手前から読み込む |
初心者が一番間違えやすいのは、「重い画像だからヒーローもlazyにする」という判断です。ChromeのLCPガイドでも、LCP画像はHTMLからすぐ見つかり、優先され、loading=lazyを避けるべきだと説明されています。Lazy Loadingは、重要なものを遅らせる技術ではなく、まだ見えていないものを後回しにする技術です。
そのまま使えるHTML
まずはフレームワークなしで使えるHTMLです。1枚目はファーストビューのヒーロー画像なのでloading="eager"とfetchpriority="high"を使います。2枚目は記事下部や商品一覧にある画像なのでloading="lazy"にします。
<img
class="hero-image"
src="/images/hero/product-dashboard-1200.webp"
srcset="
/images/hero/product-dashboard-640.webp 640w,
/images/hero/product-dashboard-1200.webp 1200w
"
sizes="100vw"
alt="商品ダッシュボードのファーストビュー"
width="1200"
height="675"
loading="eager"
fetchpriority="high"
decoding="sync"
/>
<img
class="article-image"
src="/images/articles/setup-step-800.webp"
srcset="
/images/articles/setup-step-400.webp 400w,
/images/articles/setup-step-800.webp 800w
"
sizes="(max-width: 720px) 100vw, 720px"
alt="設定手順のスクリーンショット"
width="800"
height="450"
loading="lazy"
decoding="async"
/>
decoding="async"は、画像のデコードを他の描画と並行しやすくするヒントです。常に劇的に速くなる属性ではありませんが、記事中の画像や一覧サムネイルでは自然な初期値です。ヒーロー画像ではsyncにするか、実測してasyncのままにするかを選びます。重要なのは、属性を雰囲気で選ばず、LCPと見た目の安定性を測ることです。
CLSを防ぐCSS
CLSはCumulative Layout Shiftの略で、読み込み中にレイアウトがどれだけズレたかを表す指標です。画像が後から高さを持つと、本文やCTAが下に押し出されます。読者はタップしようとしたボタンを押し損ねますし、広告や購入導線にも悪影響が出ます。
.image-frame {
aspect-ratio: 16 / 9;
background: #f3f4f6;
overflow: hidden;
}
.image-frame > img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
@media (prefers-reduced-motion: no-preference) {
.image-frame > img {
transition: opacity 180ms ease-out;
}
}
widthとheight属性があると、ブラウザは画像ファイルの取得前から比率を計算できます。CMSから画像サイズが取れるなら、必ず保存してテンプレートへ渡してください。どうしてもサイズが不明な外部画像を扱う場合は、コンテナにaspect-ratioを置き、実画像はobject-fitで収めるのが現実的です。
Reactで共通コンポーネント化する
Claude CodeにReact実装を依頼する場合は、「ヒーローだけ優先」「それ以外は遅延」「寸法は必須」という契約をコンポーネントに閉じ込めると安全です。下の例はNext.js専用ではなく、通常のReactでも使えるimgラッパーです。
type SmartImageProps = {
src: string;
srcSet?: string;
sizes?: string;
alt: string;
width: number;
height: number;
priority?: boolean;
className?: string;
};
export function SmartImage({
src,
srcSet,
sizes,
alt,
width,
height,
priority = false,
className,
}: SmartImageProps) {
const loading = priority ? "eager" : "lazy";
const fetchPriority = priority ? "high" : "auto";
const decoding = priority ? "sync" : "async";
return (
<span
className={`image-frame ${className ?? ""}`}
style={{ aspectRatio: `${width} / ${height}` }}
>
<img
src={src}
srcSet={srcSet}
sizes={sizes}
alt={alt}
width={width}
height={height}
loading={loading}
fetchPriority={fetchPriority}
decoding={decoding}
/>
</span>
);
}
このコンポーネントを使うと、商品詳細ページのメイン画像だけpriority、レビュー画像や関連記事画像は通常のlazy、という運用にできます。Claude Codeには「すべての画像をこのコンポーネントへ置き換えて」ではなく、「ファーストビュー画像はpriority、それ以外だけ移行して」と指示する方が失敗しにくいです。
4つの実用ユースケース
1つ目はECの商品一覧です。最初の8商品はファーストビューに入る可能性があるので、無理にlazyへ寄せません。9商品目以降、レビュー画像、関連商品、閲覧履歴はloading="lazy"で十分です。失敗例は、全商品画像にfetchpriority="high"を付けることです。ブラウザの優先度判断を壊し、CSSやフォントの取得が遅れることがあります。
2つ目はメディア記事や手順記事です。冒頭のアイキャッチはLCP候補なのでeager、本文中のスクリーンショットや図解はlazyにします。コード例が多い記事では、画像が本文を押し下げないようにwidthとheightを必ず入れます。失敗例は、ぼかしプレースホルダーを背景画像だけで作り、実画像のaltを空にしてしまうことです。検索エンジンとスクリーンリーダーに内容が伝わりません。
3つ目はSaaSダッシュボードです。ユーザーアイコン、顧客ロゴ、レポートのサムネイルは大量に並びがちです。見えていない行をlazyにすると効果があります。ただし、上部の主要グラフやオンボーディングCTAに関係する画像を遅らせると、体感速度ではなく操作開始が遅くなります。収益につながるCTA付近は、速度だけでなくクリックしやすさも一緒に確認します。計測設計はClaude Codeでアナリティクス実装へつなげると運用しやすくなります。
4つ目として、画像ギャラリーや横スクロールのカルーセルがあります。ここではネイティブlazyだけで十分な場合もありますが、スライドがdisplay: noneになっている、スクロールコンテナ内にある、先読み距離を制御したい、という条件ではIntersectionObserverを使う価値があります。
IntersectionObserverを使う場面
ネイティブlazyはまず最初に選ぶべき方法です。ただし、画像を表示直前に差し替えたい、読み込み開始を300px手前にしたい、読み込み後にクラスを外したい、といった高度な制御ではIntersectionObserverが向いています。
<img
class="js-lazy-image"
src="/images/placeholders/report-thumb.svg"
data-src="/images/reports/report-2026.webp"
data-srcset="/images/reports/report-2026.webp 1x"
alt="月次レポートのサムネイル"
width="640"
height="360"
/>
const lazyImages = document.querySelectorAll("img[data-src]");
function loadImage(img) {
img.src = img.dataset.src;
if (img.dataset.srcset) {
img.srcset = img.dataset.srcset;
}
img.removeAttribute("data-src");
img.removeAttribute("data-srcset");
}
if ("IntersectionObserver" in window) {
const observer = new IntersectionObserver((entries, currentObserver) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
loadImage(entry.target);
currentObserver.unobserve(entry.target);
});
}, {
rootMargin: "300px 0px",
threshold: 0.01,
});
lazyImages.forEach((image) => observer.observe(image));
} else {
lazyImages.forEach(loadImage);
}
ここでもwidthとheightは残します。data-srcへ逃がした画像は、JavaScriptが失敗したときに読み込まれない可能性があります。重要画像やSEO上の主要画像には、まず通常のsrcを使ってください。IntersectionObserverは、必要な場面だけに絞るのが安全です。
計測の手順
実装後は、見た目の速さではなく数字で確認します。Core Web Vitalsの目安は、LCPが2.5秒以内、INPが200ミリ秒以内、CLSが0.1以下です。記事の画像遅延読み込みでは、特にLCPとCLSを見ます。
npm install web-vitals
import { onCLS, onINP, onLCP } from "web-vitals";
onLCP((metric) => {
const lastEntry = metric.entries.at(-1);
console.log("LCP", metric.value, lastEntry?.element);
});
onCLS((metric) => {
console.log("CLS", metric.value, metric.entries);
});
onINP((metric) => {
console.log("INP", metric.value, metric.entries);
});
ローカルではChrome DevToolsのPerformanceパネルで、LCP要素がヒーロー画像になっているか、画像リクエストがHTMLから早く見つかっているか、レイアウトシフトがどの要素で発生しているかを見ます。公開後はPageSpeed InsightsやSearch Consoleのデータで、モバイル実ユーザーの傾向を確認します。Lighthouseだけで判断しないことも大切です。ラボ環境では速くても、実ユーザーの通信環境では別の画像がボトルネックになることがあります。
Claude Codeに渡す安全な依頼
画像最適化は、Claude Codeが一括置換しやすい領域です。だからこそ、範囲、禁止事項、検証を先に書きます。以下のような依頼なら、ヒーロー画像を誤ってlazyにする事故を減らせます。
{
"goal": "画像の遅延読み込みを安全に追加する",
"scope": [
"記事本文と商品一覧の画像だけを対象にする",
"ファーストビューとLCP候補はlazyにしない"
],
"rules": [
"すべてのimgにalt、width、heightを残す",
"下部画像にはloading=\"lazy\"とdecoding=\"async\"を使う",
"ヒーロー画像にはloading=\"eager\"または省略を使う",
"fetchpriority=\"high\"はLCP候補1枚までにする"
],
"verification": [
"コードフェンスとMDX構文を確認する",
"Chrome DevToolsでLCP要素とCLSを確認する",
"モバイル幅で画像、CTA、本文が重ならないか見る"
]
}
Claude Codeへの追加指示では、「変更前後の差分」「lazyにしなかった画像の理由」「測定で見るべき指標」を報告させます。実装だけを頼むより、判断ログを残す方が次回の改善に使えます。
失敗例チェックリスト
- ヒーロー画像、商品詳細のメイン画像、上部CTAの背景画像をlazyにしていないか。
widthとheightを消してCLSを増やしていないか。- すべての画像に
fetchpriority="high"を付けていないか。 srcsetの候補画像が同じアスペクト比になっているか。- CSS背景画像に
loading属性を付けようとしていないか。 altを空にして、意味のある図解を装飾扱いにしていないか。- JavaScript無効時に重要画像が完全に消えないか。
- プレースホルダーが本画像より目立ち、読者を誤誘導していないか。
収益導線へつなげる
画像の遅延読み込みは、単なるスコア改善ではありません。記事では読了率、商品ページでは購入ボタンの見え方、SaaSでは初回操作までの時間に影響します。ClaudeCodeLabの運用では、まず無料チートシートで日常のClaude Code依頼を固め、実装テンプレートやレビュー観点が必要になったら商品一覧へ進み、チームで速度・SEO・CTAまでまとめて改善する場合はClaude Code研修・導入相談へつなげる流れにしています。
この記事で紹介した内容を実際に試した結果、最も効いたのは「lazyを足す」ことではなく「lazyにしない画像を先に決める」ことでした。Masaの検証では、ヒーロー画像をeager、本文下部のスクリーンショットをlazy、全画像に寸法指定、srcsetでモバイル画像を分岐、という順番にすると、LCPとCLSの悪化を避けながら転送量を下げられました。Claude Codeには最初から失敗例と検証項目を渡す方が、あとでヒーロー画像を戻す手戻りが少なくなります。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Code権限セーフティラダー: 初心者がallowを広げる順番
Claude Codeの権限をread-onlyからbuild、限定編集、deploy確認まで段階的に広げる安全な運用手順。
Claude Code Small PR Proof Pack: 小さなPRをレビュー可能にする証拠セット
Claude Codeの小さなPRに、差分・検証・公開URL・CTA・rollbackを添える実務チェックリスト。
Claude Codeのコミット前レビューゲート: 差分、テスト、CTAをまとめて止める型
Claude Codeでcommit前に差分をレビューする実践手順。build、公開URL、CTA、Gumroadリンク、未翻訳本文を検知します。