アートディレクションでデバイス別に画像を出し分ける - picture 要素と media 属性の実践
アートディレクションとは - 解像度切り替えとの違い
レスポンシブ画像には 2 つの異なるアプローチがあります。「解像度切り替え (Resolution Switching)」は同じ構図の画像を異なるサイズで提供するもので、srcset と sizes 属性で実現します。一方「アートディレクション (Art Direction)」は、デバイスの画面サイズに応じて構図そのものを変える手法です。
なぜアートディレクションが必要か:
- 構図の問題: デスクトップ向けの横長ワイド画像をそのままモバイルに縮小すると、被写体が小さくなりすぎて何が写っているか分からなくなる
- 情報の優先度: モバイルでは画面が小さいため、最も重要な被写体にクロップした画像を表示すべき
- レイアウトの違い: デスクトップでは 16:9 のヒーロー画像が適切でも、モバイルでは 1:1 や 4:5 の縦長画像の方がスクロール量を抑えられる
具体例: EC サイトの商品画像で、デスクトップでは商品全体 + 使用シーンを含むワイドショットを表示し、モバイルでは商品のクローズアップを表示する。ニュースサイトのヒーロー画像で、デスクトップでは風景全体を見せ、モバイルでは人物の顔にフォーカスした縦長クロップを表示する。
アートディレクションは <picture> 要素と <source> 要素の media 属性で実現します。ブラウザは media 条件に一致する最初の <source> を選択し、一致しなければ <img> のフォールバックを使用します。
picture 要素の基本構文とブラウザの選択ロジック
<picture> 要素は複数の <source> 要素と 1 つの <img> 要素で構成されます。ブラウザは上から順に <source> を評価し、media と type の条件に一致する最初のソースを使用します。
基本構文:
<picture><source media="(min-width: 1024px)" srcset="hero-wide.webp" type="image/webp" /><source media="(min-width: 1024px)" srcset="hero-wide.jpg" /><source media="(min-width: 640px)" srcset="hero-medium.webp" type="image/webp" /><source media="(min-width: 640px)" srcset="hero-medium.jpg" /><source srcset="hero-mobile.webp" type="image/webp" /><img src="hero-mobile.jpg" alt="ヒーロー画像の説明" width="400" height="500" loading="eager" /></picture>
ブラウザの選択ロジック:
- Step 1: 上から順に
<source>のmedia属性を評価する。現在のビューポートに一致するか判定 - Step 2:
mediaが一致した<source>のtype属性を確認する。ブラウザがそのフォーマットをサポートしているか判定 - Step 3: 両方の条件を満たす最初の
<source>のsrcsetから画像を読み込む - Step 4: どの
<source>にも一致しない場合、<img>のsrcをフォールバックとして使用する
重要な注意点:
<img>要素は必須。<picture>内に<img>がないと画像は表示されないalt、width、height、loadingなどの属性は<img>に設定する (<source>には設定しない)- CSS のスタイリングは
<img>に対して行う。<picture>や<source>にスタイルを当てても効果がない
ブレークポイント設計とクロップ戦略
アートディレクションのブレークポイントは、CSS のレスポンシブブレークポイントと必ずしも一致させる必要はありません。画像の構図が破綻するポイントを基準に設計します。
推奨ブレークポイント戦略:
- モバイル (〜639px): 縦長または正方形のクロップ。被写体を大きく見せる。アスペクト比 1:1、4:5、3:4 が適切
- タブレット (640px〜1,023 px): 中間的な構図。デスクトップほどワイドではないが、モバイルほどクロップしない。アスペクト比 4:3、3:2
- デスクトップ (1,024 px〜): ワイドな構図。背景や文脈を含む全体像を表示。アスペクト比 16:9、21:9
クロップ戦略の設計:
- 被写体中心クロップ: 最も重要な被写体を中心に据え、画面サイズに応じて周囲をトリミングする。人物写真では顔を中心にクロップ
- 焦点エリアの定義: 画像内の「絶対に切り取ってはいけない領域」を事前に定義し、その領域が全デバイスで表示されることを保証する
- テキストオーバーレイとの整合: ヒーロー画像にテキストを重ねる場合、テキスト配置領域と被写体が重ならないようにデバイスごとにクロップ位置を調整する
CMS との連携: WordPress や Contentful などの CMS では、画像アップロード時に焦点ポイント (focal point) を設定できる機能があります。この焦点ポイントを基準に、各ブレークポイント用のクロップを自動生成するワークフローを構築すると、運用効率が大幅に向上します。Cloudinary の g_auto (AI 自動クロップ) や imgix の fit=crop&crop=faces も活用できます。
srcset と sizes の組み合わせ - 解像度とアートディレクションの併用
アートディレクション (<picture> + media) と解像度切り替え (srcset + sizes) は組み合わせて使用できます。各ブレークポイントの構図内で、さらにデバイスピクセル比 (DPR) に応じた解像度の画像を提供する設計です。
組み合わせの例:
<picture><source media="(min-width: 1024px)" srcset="hero-wide-800.webp 800w, hero-wide-1200.webp 1200w, hero-wide-1600.webp 1600w" sizes="100vw" type="image/webp" /><source media="(min-width: 640px)" srcset="hero-medium-600.webp 600w, hero-medium-900.webp 900w" sizes="100vw" type="image/webp" /><source srcset="hero-mobile-400.webp 400w, hero-mobile-800.webp 800w" sizes="100vw" type="image/webp" /><img src="hero-mobile-400.jpg" alt="商品イメージ" width="400" height="500" /></picture>
この設計のポイント:
- media 属性: 構図 (アートディレクション) の切り替えポイントを定義する
- srcset の w 記述子: 各構図内で利用可能な解像度バリエーションを列挙する
- sizes 属性: ブラウザに画像の表示サイズを伝え、最適な解像度を選択させる
sizes の設計:
sizes="100vw": 画像がビューポート幅いっぱいに表示される場合sizes="(min-width: 1200px) 1200px, 100vw": 最大幅 1,200 px のコンテナ内に表示される場合sizes="(min-width: 768px) 50vw, 100vw": タブレット以上で 2 カラムレイアウトの場合
画像生成の自動化: 1 枚のソース画像から複数の構図 x 複数の解像度を手動で作成するのは非現実的です。Sharp (Node.js)、ImageMagick、または画像 CDN (Cloudinary, imgix) を使って自動生成するパイプラインを構築してください。
パフォーマンス最適化 - LCP とレイアウトシフトへの配慮
アートディレクション画像は多くの場合ファーストビューのヒーロー画像に使用されるため、LCP (Largest Contentful Paint) に直接影響します。パフォーマンスを最適化するための実践的なテクニックを紹介します。
LCP 最適化:
- loading="eager": ヒーロー画像には
loading="lazy"を使用しない。ファーストビューの画像は即座に読み込みを開始する - fetchpriority="high": LCP 候補の画像に
fetchpriority="high"を設定し、ブラウザに優先的にダウンロードさせる - preload:
<link rel="preload" as="image" href="hero.webp" media="(min-width: 1024px)" imagesrcset="..." />で重要な画像を事前読み込みする - 画像サイズの最適化: 各ブレークポイントの画像を必要最小限のサイズに圧縮する。WebP/AVIF を優先し、品質 75-85 で十分な視覚品質を維持
CLS (Cumulative Layout Shift) 防止:
- width/height 属性の明示:
<img>にwidthとheightを設定し、ブラウザが画像読み込み前にアスペクト比を計算できるようにする - aspect-ratio の CSS 設定: アートディレクションでアスペクト比が変わる場合、CSS メディアクエリで
aspect-ratioを切り替える - CSS 例:
.hero-img { aspect-ratio: 4/5; } @media (min-width: 640px) { .hero-img { aspect-ratio: 3/2; } } @media (min-width: 1024px) { .hero-img { aspect-ratio: 16/9; } }
プレースホルダー戦略: LQIP (Low Quality Image Placeholder) を Data URI で埋め込み、本画像の読み込み完了までぼかし表示する。各ブレークポイントの構図に合わせた LQIP を用意すると、レイアウトシフトなしで自然な読み込み体験を実現できます。
実装の自動化とテスト - 運用を見据えた設計
アートディレクション画像の運用は、画像バリエーションの生成と HTML マークアップの管理が複雑になりがちです。自動化とテストの仕組みを整備し、持続可能な運用を実現します。
画像生成パイプライン:
- Sharp (Node.js):
sharp('source.jpg').resize(800, 450, { fit: 'cover', position: 'attention' }).webp({ quality: 80 }).toFile('hero-wide-800.webp') - position: 'attention': Sharp の AI ベースの焦点検出で、重要な被写体を中心にクロップする
- バッチ処理: 1 枚のソース画像から全ブレークポイント x 全解像度 x 全フォーマットの組み合わせを自動生成するスクリプトを作成する
コンポーネント設計 (React 例):
function ResponsiveHero({ src, alt, crops }) { return (<picture>{crops.map(({ media, srcSet, type }) => (<source key={media+type} media={media} srcSet={srcSet} type={type} />))}<img src={crops[crops.length-1].fallback} alt={alt} width={crops[0].width} height={crops[0].height} loading="eager" fetchPriority="high" /></picture>); }
テスト戦略:
- ビジュアルリグレッションテスト: Playwright や Cypress で各ブレークポイントのスクリーンショットを撮影し、意図した画像が表示されているか自動検証する
- パフォーマンステスト: Lighthouse CI で LCP スコアをモニタリングし、画像変更が LCP を悪化させていないか検証する
- レスポンシブテスト: Chrome DevTools の Device Mode で各ブレークポイントの表示を確認する。
window.matchMediaの変化に応じて正しい画像が選択されているか検証
運用上の注意: 画像バリエーションが増えるとストレージコストとビルド時間が増加します。全ページにアートディレクションを適用するのではなく、ヒーロー画像やキービジュアルなど視覚的インパクトが大きい箇所に限定して適用することを推奨します。