レスポンシブ画像の srcset と sizes は、理屈は単純なのに手書きすると途端に面倒になります。ブレークポイントごとに「この幅のとき画像は何pxで表示されるか」を先に宣言しなければならず、sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw" のような文字列をCSSのレイアウトと二重管理することになります。書き間違えるとブラウザは想定より大きな画像を掴んだり、逆に小さすぎる画像を引き伸ばしたりします。前者は転送量の無駄、後者は画質劣化、そしてどちらも LCP(Largest Contentful Paint)の悪化 につながります。Safari 27では、この手計算から解放される sizes="auto" に対応しました。この記事では従来の書き方との対比、遅延読み込みと組み合わせる理由、3ブラウザの対応状況、Next.jsでの運用までを整理します。
Before: sizes手計算のつらさ
従来の sizes は、いわばブラウザへの「事前申告」です。画像の読み込み時点ではCSSレイアウトがまだ確定していないことが多いため、ブラウザは sizes の宣言だけを頼りに「この画像は最終的に何pxで表示されそうか」を推測し、srcset の候補から1枚を選びます。宣言がレイアウトと食い違うと、最適な候補を選べません。たとえば2カラムの記事一覧では、モバイルで1カラム(100vw)、タブレットで2カラム(50vw)、PCで3カラム(33vw)といった具合に、ブレークポイントごとの表示幅を全部書き下す必要がありました。
<img
src="thumb-800.jpg"
srcset="thumb-400.jpg 400w, thumb-800.jpg 800w, thumb-1200.jpg 1200w"
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
loading="lazy"
decoding="async"
width="800"
height="450"
alt="記事サムネイル" />この書き方の問題は3つあります。第一に、CSSの grid-template-columns やコンテナの max-width を変えるたびに sizes も直さなければならず、二重管理になります。第二に、カードの余白(gap)やpaddingを引いた実表示幅までは書ききれないので、どうしても概算になります。第三に、コピー&ペーストで別ページに流用したときに古いブレークポイントが残り、誰も気づかないまま過大な画像を読み続ける事故が起きます。実案件では「PCでは3カラムなのに sizes が 100vw のまま」で、毎回1200w級の画像を12枚読んでいた事例もありました。転送量が増えるだけでなく、帯域の細いモバイル回線ではLCPが素直に悪化します。
既存サイトの
sizesが正しいかは、DevToolsのNetworkパネルで画像の転送サイズと、Elementsパネルで測った実表示幅を比べると分かります。実表示幅の2倍(DPR 2x相当)を超える候補ばかり選ばれていたら、sizesの宣言が実レイアウトより大きく見積もられています。
After: loading=lazy + sizes=auto
sizes="auto" は、この「事前申告」をやめて「実測」に切り替える指定です。仕組みの鍵は loading="lazy" との組み合わせにあります。通常の(eagerな)画像は、レイアウトが確定する前にプリロードスキャナが先読みするため、ブラウザは sizes の宣言なしには候補を選べません。一方、遅延読み込みの画像はすぐには取得されず、スクロールが近づいてレイアウトが確定してから読み込みが始まります。その時点では「この img が実際に何pxで表示されるか」が分かっているので、ブラウザが自分で実測して srcset から最適な1枚を選べます。これが sizes="auto" のタイミングの理屈です。開発者がブレークポイントを列挙しなくても、コンテナの幅・gap・paddingを反映した正確な選択ができます。
<!-- 遅延読み込みの画像は sizes="auto" に置き換えられる -->
<img
src="thumb-800.jpg"
srcset="thumb-400.jpg 400w, thumb-800.jpg 800w, thumb-1200.jpg 1200w"
sizes="auto"
loading="lazy"
decoding="async"
width="800"
height="450"
alt="記事サムネイル" />
<!-- ヒーロー画像など即時表示が必要な画像には使えない -->
<img
src="hero-1600.jpg"
srcset="hero-800.jpg 800w, hero-1600.jpg 1600w, hero-2400.jpg 2400w"
sizes="100vw"
fetchpriority="high"
decoding="async"
width="1600"
height="900"
alt="ヒーロー画像" />重要な注意点として、sizes="auto" は loading="lazy" とセットで使います。ヒーロー画像やファーストビューのメインビジュアルのような非遅延(eager)の画像では、レイアウト確定を待っていては読み込み開始が遅れ、かえってLCPを悪化させます。仕様上も auto は遅延読み込み画像向けであり、eagerな画像に付けても自動計算は働きません。使い分けはシンプルです。ファーストビューの1枚は手書きの sizes と fetchpriority="high" で最速化し、スクロール先の一覧画像・本文内画像は loading="lazy" + sizes="auto" で正確化する。この二段構えが現時点の正解です。また width / height 属性は auto の有無にかかわらず必ず付けます。読み込み前のレイアウトシフト(CLS)防止と、実測選択の基準になるためです。
decoding="async"とloading="lazy"は何が違うの?→loading="lazy"は「いつ取得するか」(視界に近づくまで待つ)の指定で、decoding="async"は「取得後にいつ復号するか」(メインスレッドを塞がず裏で復号)の指定です。sizes="auto"の実測に効くのは前者のタイミングです。両者は併用できます。
Chromeではどうなの?
この機能自体は新しくありません。Chromeでは2年前から実装されており、現場ではすでに常識として使われています。Safari 27でSafariが追いついたことで、ようやく「3ブラウザ全部で使える」状態になりました。対応状況は次の通りです。
ブラウザ | sizes="auto" の対応 | 備考 |
|---|---|---|
Chrome / Edge | 126以降で対応 | 2024年から利用可能。現場の標準 |
Firefox | 150以降で対応 | 遅延読み込み画像の自動選択に対応 |
Safari | 27で対応 | リリースノートに記載あり。caniuseは2026年8月時点で未更新のためSafari Technology Previewでの実測推奨 |
最新の対応状況は caniuse: sizes="auto" で確認できます。注意点として、caniuse側のSafari欄は2026年8月時点ではまだ未更新のため、緑になっていなくても悲観する必要はありません。一次情報であるSafari 27のリリースノートには対応が明記されており、Safari Technology Previewでの実測でも動作が確認できます。結論は明快です。Chromeでは2年前から常識だったものに、Safariが追いついて全面解禁になった。これからは「lazy画像には auto を付ける」を既定値にして問題ありません。
LCPとの関係も整理しておきます。sizes="auto" は万能ではなく、適用先によって役割が分かれます。
画像の種類 | 推奨指定 | 理由 |
|---|---|---|
ヒーロー画像(LCP要素) | 手書きsizes + eager + fetchpriority="high" | 先読みで最速開始。autoは待機が発生し逆効果 |
一覧・本文内のlazy画像 | sizes="auto" + loading="lazy" | 実測で最適候補を選択。転送量削減 |
アイコン・装飾の小画像 | srcset自体が不要なことも多い | 候補を増やすより1枚+CSS指定が軽い |
ヒーロー画像かどうかの判定は、Lighthouseの「LCP element」表示か、WebPageTestのフィルムストリップで確認します。ファーストビューで最大面積になる画像だけをeager+手書きsizesにし、それ以外は迷わず
sizes="auto"に寄せるのが安全です。
Next.jsでの運用
Next.jsの next/image を使っている場合も、考え方は同じです。next/image は sizes プロパティを渡す設計になっており、最終的に出力される img タグの sizes 属性に反映されます。つまり「ブレークポイントごとの表示幅を宣言する」という発想自体は変わりません。遅延読み込みの一覧画像では sizes に実レイアウトに合う値を渡し、ファーストビューの画像は優先読み込み側に倒す、という使い分けが基本になります。
運用上のコツは、sizes の値をページごとに場当たり的に書くのではなく、グリッドの列数と連動させて定数化することです。たとえば「記事一覧はモバイル1列・タブレット2列・PC3列」というレイアウトが決まっているなら、その対応表を1か所にまとめ、全カードで同じ値を参照します。こうしておけば、将来グリッドを4列に変えたときの修正箇所が1か所で済み、Before節で触れた「古いブレークポイントの残置」事故を防げます。断定的なAPI仕様の話はここでは踏み込みませんが、どのバージョンでも「出力されるHTMLの sizes が実レイアウトと一致しているか」をDevToolsで確かめる習慣が有効です。最適化コンポーネントを使っていても、最終的にブラウザが見るのはただの img タグだからです。
<!-- next/image の出力をDevToolsで見たときの目安(概念図) -->
<!-- 一覧カード: 遅延読み込みなので auto で実測に任せる -->
<img srcset="card-400.jpg 400w, card-800.jpg 800w, card-1200.jpg 1200w"
sizes="auto" loading="lazy" decoding="async"
width="800" height="450" alt="記事カード" />
<!-- ヒーロー: 先読みするので表示幅を明示する -->
<img srcset="hero-800.jpg 800w, hero-1600.jpg 1600w"
sizes="100vw" fetchpriority="high" decoding="async"
width="1600" height="900" alt="ヒーロー" />まとめ
手書きの sizes はレイアウトとの二重管理であり、書き間違えは転送量とLCPに直結します。遅延読み込みの画像は sizes="auto" に置き換え、実測選択に任せるのが安全です。ヒーロー画像だけは手書き sizes とeagerのまま残し、Safari 27以降の3ブラウザでこの二段構えを標準にしましょう。
参考リンク
- Safari 27 Release Notes:
sizes="auto"対応の一次情報。Safari Technology Previewでの実測と併せて確認する - MDN: HTMLImageElement.sizes:
sizesプロパティとautoキーワードの仕様・値の形式 - caniuse: sizes="auto":ブラウザ別の対応状況(Safari欄は2026年8月時点で未更新のため注意)






