レスポンシブ画像
問題
画像はレイアウトの問題やパフォーマンス低下の最も一般的な原因の一つです。AIエージェントは固定幅の <img> タグを出力し、object-fit を忘れ(画像が引き伸ばされたり潰れたりする)、aspect-ratio を省略し(レイアウトシフトが発生する)、適切な srcset/sizes 属性や <picture> 要素によるアートディレクションもほとんど生成しません。
解決方法
レスポンシブ画像には、視覚的な表示のためのCSSテクニック(object-fit、aspect-ratio)と、パフォーマンスとアートディレクションのためのHTML属性(srcset、sizes、<picture>)の両方が必要です。
object-fit の比較: cover vs contain vs fill
コード例
object-fit で画像の引き伸ばしを防ぐ
object-fit プロパティは、背景画像における background-size と同様に、画像がコンテナをどのように満たすかを制御します。
/* Fills the container, cropping to maintain aspect ratio */
.image-cover {
width: 100%;
height: 300px;
object-fit: cover;
}
/* Fits entirely within the container, letterboxing if needed */
.image-contain {
width: 100%;
height: 300px;
object-fit: contain;
}
object-position でトリミング位置を制御する
/* Focus on the top of the image when cropping */
.image-top {
width: 100%;
height: 200px;
object-fit: cover;
object-position: center top;
}
/* Focus on a specific area */
.image-focal {
width: 100%;
height: 200px;
object-fit: cover;
object-position: 30% 20%;
}
aspect-ratio でレイアウトシフトを防ぐ
.card__image {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
}
.avatar {
width: 3rem;
aspect-ratio: 1;
object-fit: cover;
border-radius: 50%;
}
.hero-image {
width: 100%;
aspect-ratio: 21 / 9;
object-fit: cover;
}
max-width による基本的なレスポンシブ画像
img {
max-width: 100%;
height: auto;
}
これはすべてのプロジェクトが画像に適用すべき最低限のCSSです。アスペクト比を維持しながら、画像がコンテナからはみ出すのを防ぎます。
srcset と sizes による解像度の切り替え
srcset を使って複数の画像サイズを提供し、sizes でさまざまなビューポート幅での画像の表示幅をブラウザに伝えます。
<img
src="photo-800.jpg"
srcset="
photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w,
photo-1600.jpg 1600w
"
sizes="
(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
33vw
"
alt="A descriptive alt text"
width="800"
height="450"
loading="lazy"
/>
srcsetは利用可能な画像ファイルとその固有の幅をリストします。sizesはさまざまなビューポート幅でのレイアウト上の画像幅を記述します。- ブラウザはビューポート幅とデバイスピクセル比に基づいて最適なファイルを選択します。
widthとheight属性は、画像がロードされる前のアスペクト比計算のための固有の寸法を提供します。
picture 要素によるアートディレクション
異なるビューポート幅で完全に異なる画像(異なるトリミング、異なるコンテンツ)を提供する必要がある場合は <picture> を使いましょう。
<picture>
<source
media="(min-width: 1024px)"
srcset="hero-wide.jpg"
/>
<source
media="(min-width: 600px)"
srcset="hero-medium.jpg"
/>
<img
src="hero-mobile.jpg"
alt="Hero image"
width="600"
height="400"
loading="lazy"
/>
</picture>
picture によるフォーマットの切り替え
モダンフォーマットをフォールバック付きで提供します:
<picture>
<source type="image/avif" srcset="photo.avif" />
<source type="image/webp" srcset="photo.webp" />
<img src="photo.jpg" alt="Description" width="800" height="600" />
</picture>
完全なレスポンシブ画像パターン
すべてのテクニックを組み合わせた例:
<picture>
<source
type="image/avif"
srcset="photo-400.avif 400w, photo-800.avif 800w, photo-1200.avif 1200w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
<source
type="image/webp"
srcset="photo-400.webp 400w, photo-800.webp 800w, photo-1200.webp 1200w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
alt="A descriptive alt text"
width="800"
height="600"
loading="lazy"
decoding="async"
/>
</picture>
picture img {
width: 100%;
height: auto;
aspect-ratio: 4 / 3;
object-fit: cover;
}
AIがよくやるミス
object-fitを忘れる:object-fit: coverなしで画像に固定のwidthとheightを設定し、画像が引き伸ばされたり潰れたりしてしまいます。aspect-ratioがない:aspect-ratioを省略すると、画像のロード時にレイアウトシフト(CLS)が発生します。widthとheight属性がない: これらのHTML属性により、ブラウザは画像がロードされる前にアスペクト比を計算でき、レイアウトシフトを防ぎます。srcsetやsizesがない: すべてのデバイスに単一の大きな画像ファイルを配信すると、モバイルで帯域幅を無駄にします。sizesの値が不正確: 画像がビューポートの一部しか占めないのにsizes="100vw"を使うと、ブラウザが過大なファイルをダウンロードしてしまいます。- コンテンツ画像に
background-imageを使う: コンテンツ画像はアクセシビリティ(alt テキスト)とパフォーマンス(遅延読み込み)のために<img>を使うべきです。background-imageは装飾的な画像に使いましょう。 loading="lazy"を忘れる: ファーストビュー外の画像にはloading="lazy"を使って読み込みを遅延させましょう。ただし、LCP(Largest Contentful Paint)画像(通常はヒーロー画像)を遅延読み込みしてはいけません。
使い分け
object-fit: cover: カードサムネイル、ヒーロー画像、アバターなど、固定サイズの画像コンテナに使いましょう。aspect-ratio: 画像が固定コンテナを持ち、レイアウトシフトを防ぐ必要がある場合に使いましょう。srcset+sizes: 複数のビューポートコンテキストで提供される画像に使いましょう。これは本番画像の標準です。<picture>: アートディレクション(異なるサイズでの異なるトリミング)やフォーマット切り替え(AVIF/WebP と JPEG フォールバック)に使いましょう。loading="lazy": ファーストビュー外のすべての画像に使いましょう。