レスポンシブ画像の出し分け戦略|srcsetとpictureを完全マスターする
こんにちは!
今日は「レスポンシブ画像の出し分け戦略」について解説します。
単純にメディアクエリだけでレスポンシブ対応させてると、実はめっちゃ損してるんですよ。
単純なCSSリサイズがダメな理由
僕も最初は気付かなかったんですけど、「PCでは大きい画像を読み込んで、CSSでmax-width: 100%にすれば大丈夫」って思ってました。
ほんまにこれ、初心者あるあるやん。
例えば、PCビューで2000px幅の高画質画像を用意したとします。
それをスマホで表示する場合、CSSでサイズを縮小しても、ブラウザは相変わらず2000px分のデータを丸ごとダウンロードしてるんです。
これって通信量が無駄になるし、ページの読み込みも遅くなるし、ユーザーのモバイル環境にも優しくないですよね。
つまり、CSSは「見た目」を制御するだけで、「実際に読み込むデータ量」には影響しないんです。
ここが多くの人が見落とすポイントです。
本当のレスポンシブ画像実装は、「デバイスごとに最適なサイズの画像を読み込む」というのが正解なんですよ。
srcsetで複数サイズの画像を準備する
では、どうやって出し分けるのか?
一番シンプルで使いやすいのがsrcset属性です。
まず、1つの画像に対して複数のサイズを用意します。
例えば、一眼レフ風の製品画像なら:
product-small.jpg(600px幅)product-medium.jpg(1000px幅)product-large.jpg(1800px幅)
そして、HTMLにこう書きます:
<img
src="product-small.jpg"
srcset="
product-small.jpg 600w,
product-medium.jpg 1000w,
product-large.jpg 1800w
"
alt="おしゃれな製品写真"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
>
ちょっと複雑に見えるかもしれませんが、仕組みは簡単です。600w、1000w、1800wのwは「画像の実際の幅」を表してます。
そしてsizes属性で「このメディアクエリの時は、ビューポートの何%の幅で表示されるのか」を宣言します。
上の例なら:
- スマホ(768px以下):
100vw(ビューポート幅いっぱい) - タブレット(1200px以下):
50vw(ビューポート幅の50%) - PC:
33vw(ビューポート幅の33%)
ブラウザがこの情報を持つと、「あ、スマホで100vw表示なら、600pxの画像で十分だな」と判断して、その画像だけをダウンロードします。
めっちゃ効率的でしょ?
実装で気をつけるポイントは、src属性には必ず一番小さい画像を指定することです。
これはsrcsetに対応していない古いブラウザでも、最低限表示できるようにするためです。
pictureで複雑な出し分けに対応する
でも、案件によっては「スマホとPCで全く違う画像を使いたい」ってことありますよね。
例えば、ランディングページのヒーロー画像で、PCでは横長、スマホでは縦長の別画像にしたいとか。
そんな時は<picture>要素を使うといいですよ。
<picture>
<source
media="(max-width: 768px)"
srcset="hero-mobile.jpg 1x, hero-mobile-2x.jpg 2x"
>
<source
media="(max-width: 1200px)"
srcset="hero-tablet.jpg 1x, hero-tablet-2x.jpg 2x"
>
<img
src="hero-desktop.jpg"
srcset="hero-desktop.jpg 1x, hero-desktop-2x.jpg 2x"
alt="ランディングページのヒーロー画像"
>
</picture>
<picture>の中には複数の<source>を書けます。
上から順にメディアクエリを評価して、最初にマッチしたものが使われます。
ここで面白いのが、1xと2xの指定です。1xは標準解像度、2xはRetinaディスプレイなどの高解像度用です。
つまり、「スマホで画面密度が高い場合は、より高品質な画像を読み込む」という最適化ができるわけです。
僕の現場経験では、このレベルまでやっぱり実装してる案件はまだ少ないですね。
でも、ほんまにこういう細かい最適化が、ページ速度とか、ユーザー体験につながるんですよ。
実装時の落とし穴と対策
最後に、現場でよく見かけるハマりポイントを紹介します。
落とし穴1:sizes属性を書き忘れる
srcsetだけ書いてsizesを忘れると、ブラウザが画像サイズを判断できません。
結果、でかい画像を読み込んでしまうことがあります。
必ず両方セットで考えてください。
落とし穴2:picture要素での順序ミス
<picture>では最初にマッチしたものが使われるので、条件の順序が大事です。
広い条件から狭い条件の順に書きましょう。
逆だと、いつも最初の条件にマッチしちゃいます。
落とし穴3:ファイル名の管理が複雑になる
複数の画像ファイルを用意すると、ファイル管理が大変になります。
命名規則を決めておくといいですよ。
例えば、product-[name]-[width]w.jpgみたいなフォーマットにして、自分たちのアセット管理の仕組みに入れとくといいです。
僕のチームでは、Figmaから自動生成するスクリプト使ってるんですけど、手作業だと本当に大