Retina ディスプレイ対応画像の作り方 - 高 DPI 環境での鮮明な表示を実現する
なぜ Retina ディスプレイで画像がぼやけるのか - デバイスピクセル比の仕組み
Retina ディスプレイ (Apple の商標) や高 DPI ディスプレイでは、1 つの CSS ピクセルが複数の物理ピクセルで表示されます。この比率をデバイスピクセル比 (Device Pixel Ratio, DPR) と呼びます。DPR が 2 のディスプレイでは、1 CSS ピクセルが 2x2 = 4 物理ピクセルで描画されます。
画像がぼやける原因:
- ピクセル不足: CSS で
width: 300pxと指定した画像が実際には 300px の解像度しか持たない場合、DPR 2 のディスプレイでは 600 物理ピクセルの領域に 300px の画像を引き伸ばして表示します。この拡大処理により、画像がぼやけて見えます - バイリニア補間: ブラウザは画像を拡大する際にバイリニア補間 (隣接ピクセルの平均値で中間ピクセルを生成) を行います。これにより、シャープなエッジがぼやけ、テキストや線画が特に劣化して見えます
- サブピクセルレンダリングの不一致: 物理ピクセルと画像ピクセルが 1:1 で対応しないため、サブピクセルレンダリングが正しく機能せず、特にテキストを含む画像で顕著な品質低下が発生します
現在の主要デバイスの DPR:
- iPhone 15 / 16 シリーズ: DPR 3
- MacBook Pro / Air (Retina): DPR 2
- iPad Pro: DPR 2
- Samsung Galaxy S シリーズ: DPR 2.625-3.5
- 一般的な Windows ノート PC: DPR 1.25-2
- 4K モニター (スケーリング 150%): DPR 1.5
JavaScript で現在のデバイスの DPR を取得するには window.devicePixelRatio を参照します。CSS メディアクエリでは @media (min-resolution: 2dppx) で高 DPI デバイスを判定できます。
srcset 属性による解像度切り替え - HTML での基本実装
HTML の srcset 属性は、ブラウザがデバイスの DPR に応じて最適な解像度の画像を自動選択する仕組みを提供します。開発者が複数の解像度の画像を用意し、ブラウザに選択を委ねることで、各デバイスに最適な画像を配信できます。
基本的な記述方法:
<img src="image-1x.jpg" srcset="image-1x.jpg 1x, image-2x.jpg 2x, image-3x.jpg 3x" alt="説明" width="300" height="200">
この記述により、DPR 1 のデバイスには image-1x.jpg (300 × 200 px)、DPR 2 のデバイスには image-2x.jpg (600 × 400 px)、DPR 3 のデバイスには image-3x.jpg (900 × 600 px) が配信されます。
w ディスクリプタを使った幅ベースの指定も可能です:
<img src="image-300w.jpg" srcset="image-300w.jpg 300w, image-600w.jpg 600w, image-900w.jpg 900w" sizes="(max-width: 600px) 100vw, 300px" alt="説明">
sizes 属性はブラウザに「この画像が画面上でどのくらいの幅で表示されるか」を伝えます。ブラウザはこの情報と DPR を組み合わせて、最適な画像を選択します。例えば、sizes="300px" で DPR 2 のデバイスなら、600w の画像が選択されます。
実装上の注意点:
src属性はsrcset非対応ブラウザへのフォールバックとして必ず設定しますwidthとheight属性を明示することで、画像読み込み前のレイアウトシフト (CLS) を防止します- ブラウザのキャッシュ状態やネットワーク速度によっては、低解像度の画像が選択される場合があります (ブラウザの最適化判断)
picture 要素とアートディレクション - デバイスに応じた画像の出し分け
<picture> 要素は srcset よりも細かい制御が可能で、デバイスの特性に応じて全く異なる画像を配信できます。これを「アートディレクション」と呼び、単なる解像度の切り替えではなく、構図やクロップ位置を変えた画像を出し分けるために使用します。
アートディレクションの実装例:
<picture>
<source media="(max-width: 767px)" srcset="hero-mobile-1x.webp 1x, hero-mobile-2x.webp 2x" type="image/webp">
<source media="(max-width: 767px)" srcset="hero-mobile-1x.jpg 1x, hero-mobile-2x.jpg 2x">
<source media="(min-width: 768px)" srcset="hero-desktop-1x.webp 1x, hero-desktop-2x.webp 2x" type="image/webp">
<source media="(min-width: 768px)" srcset="hero-desktop-1x.jpg 1x, hero-desktop-2x.jpg 2x">
<img src="hero-desktop-1x.jpg" alt="ヒーロー画像" width="1200" height="600">
</picture>
この例では、モバイルとデスクトップで異なる構図の画像を配信しつつ、各デバイスの DPR に応じた解像度も提供しています。さらに WebP 対応ブラウザには WebP を、非対応ブラウザには JPEG をフォールバックとして配信します。
アートディレクションが必要なケース:
- ヒーロー画像: デスクトップでは横長のパノラマ、モバイルでは縦長にクロップした画像を表示
- 商品画像: デスクトップでは全体像、モバイルでは商品のクローズアップを表示
- インフォグラフィック: デスクトップでは横並びレイアウト、モバイルでは縦積みに再構成した画像を表示
<picture> 要素の <source> は上から順に評価され、最初にマッチした条件の画像が使用されます。条件にマッチしない場合は <img> 要素がフォールバックとして表示されます。
CSS での高 DPI 対応 - image-set() と背景画像の最適化
CSS の背景画像やコンテンツ画像に対しても、高 DPI ディスプレイへの対応が必要です。image-set() 関数を使えば、CSS レベルでデバイスの DPR に応じた画像切り替えが可能です。
image-set() の基本構文:
.hero {
background-image: image-set(
url('bg-1x.webp') type('image/webp') 1x,
url('bg-2x.webp') type('image/webp') 2x,
url('bg-1x.jpg') type('image/jpeg') 1x,
url('bg-2x.jpg') type('image/jpeg') 2x
);
}
2026 年時点で image-set() は主要ブラウザすべてで対応していますが、古いブラウザ向けにフォールバックを提供する場合は、メディアクエリを使った方法も併用します:
.hero {
background-image: url('bg-1x.jpg');
}
@media (min-resolution: 2dppx) {
.hero {
background-image: url('bg-2x.jpg');
}
}
SVG を背景画像として使用する場合は、解像度の切り替えが不要です。SVG はベクター形式のため、どの DPR でも鮮明に表示されます。アイコン、ロゴ、パターン背景には SVG を積極的に活用することで、複数解像度の画像を用意する手間を省けます。
CSS の border-image や mask-image にも同様の高 DPI 対応が必要です。特に border-image で 1px のボーダーを画像で表現する場合、DPR 2 では 2px の画像が必要になります。この場合も image-set() またはメディアクエリで対応します。
画像書き出しワークフロー - 効率的な複数解像度の生成
Retina 対応画像を効率的に生成するためのワークフローを構築することが、運用コストの削減に直結します。手動で複数解像度を書き出すのは非現実的なため、自動化パイプラインの構築が必須です。
推奨ワークフロー:
- 元画像は最大解像度で保存: 3x (DPR 3) に対応する最大サイズで元画像を保持します。表示サイズが 300px なら、元画像は 900px 以上で保存します。ダウンスケールは品質を維持しますが、アップスケールは品質が劣化するため、常に大きい方から小さい方へ変換します
- Sharp (Node.js) による自動生成:
sharp(input).resize(600).webp({ quality: 80 }).toFile('output-2x.webp')のように、1 つのソース画像から複数サイズ・複数フォーマットを自動生成します。ビルドスクリプトに組み込めば、画像追加時に自動的に全バリエーションが生成されます - Next.js / Nuxt.js の画像最適化: フレームワークの組み込み画像コンポーネント (
next/image、nuxt-img) を使えば、srcset の生成、フォーマット変換、遅延読み込みが自動的に行われます。開発者は元画像を 1 つ用意するだけで済みます
書き出し設定の目安:
- 1x: 表示サイズと同じピクセル数。JPEG 品質 80-85、WebP 品質 75-80
- 2x: 表示サイズの 2 倍。JPEG 品質 70-75、WebP 品質 65-70 (サイズが大きいため品質を若干下げる)
- 3x: 表示サイズの 3 倍。JPEG 品質 65-70、WebP 品質 60-65
高解像度画像は品質設定を下げても、物理ピクセルが密集しているため視覚的な劣化が目立ちにくいという特性があります。2x 画像を品質 70 で書き出しても、DPR 2 のディスプレイでは 1x 品質 85 と同等以上に見えることが多いです。
パフォーマンスとのバランス - 高 DPI 対応のコスト管理
高 DPI 対応は画質向上に直結しますが、ファイルサイズの増大というコストを伴います。2x 画像は 1x の約 4 倍 (面積比)、3x 画像は約 9 倍のピクセル数を持つため、適切な最適化なしではページの読み込み速度に深刻な影響を与えます。
パフォーマンスを維持するための戦略:
- AVIF/WebP の活用: 次世代フォーマットを使えば、2x 画像でも 1x JPEG と同程度のファイルサイズに抑えられます。
<picture>要素でフォーマットと解像度の両方を最適化することで、品質とサイズの両立が可能です - 遅延読み込みの徹底: ファーストビュー外の画像には
loading="lazy"を必ず適用します。高解像度画像は特にサイズが大きいため、遅延読み込みによる初期読み込み時間の削減効果が顕著です - CDN での動的リサイズ: Cloudflare Images、CloudFront + Lambda@Edge、imgix などの画像 CDN を使えば、リクエスト時に DPR に応じた最適サイズを動的に生成・配信できます。元画像を 1 つアップロードするだけで、全デバイスに最適な画像が配信されます
- 1.5x で妥協する戦略: DPR 2 のデバイスに対して 2x ではなく 1.5x の画像を配信する戦略です。ファイルサイズを 44% 削減しつつ、視覚的な品質低下はほとんど気づかれません。特にモバイル回線では有効なトレードオフです
- SVG の積極活用: アイコン、ロゴ、図表、UI 要素は可能な限り SVG で実装します。SVG はファイルサイズが小さく、どの DPR でも鮮明に表示されるため、解像度対応の手間が完全に不要になります
Core Web Vitals への影響を監視するため、Lighthouse や PageSpeed Insights で定期的にパフォーマンスを計測し、画像サイズが LCP スコアに悪影響を与えていないか確認することが重要です。