解像度とフォーマット対応状況の両方に配慮してWebP画像やAVIF画像を扱う
こんにちは、Webサイト作ってますか? Webサイトを作っていると、Lighthouseスコアを上げるために画像のサイズやフォーマットにも気を配りたくなりますよね。
筆者は画像のフォーマットにはあまり頓着してこなかったので、「フラットな画像ならPNG」「込み入ったイラストはJPEG」「なんかWebPとかいうのもあるらしいけどよくわからん」くらいの解像度で適当に使っていました。しかし、最近の開発でLighthouseスコアのチューニングをしてみたところ、色々新しい知見が溜まったので、自分用の備忘録として残しておこうと思います。
3行まとめ
- ちゃんと複数の解像度の画像を用意しようね
- WebPやAVIFといった次世代フォーマットも使ってみようね
-
<picture>
と<source>
は便利
画像のサイズを複数用意する
表示するディスプレイの解像度に合わせて、表示する画像の大きさを調整することで、Retinaなディスプレイでもそうでないディスプレイでも画像がきれいに表示されるようになります。例えば、/images/sample.jpg
という画像を表示する場合、/images/sample.jpg
と /images/sample@2x.jpg
という2つの画像を用意しておいて、Retinaディスプレイの場合は @2x
のほうを、そうでない場合は無印のほうを表示する、といった設定は、次のように書きます。
<img
src="/images/sample.jpg"
srcset="/images/sample.jpg 1x, /images/sample@2x.jpg 2x"
>
デフォルトの表示は src
属性に書きつつ、 srcset
属性でディスプレイの解像度に応じた画像を指定します。これにより、取得しにいく画像の解像度が切り替わります。便利ですね。
WebPもAVIFも良さそうやん
画像のフォーマットにも目を向けてみると、WebPやAVIFといったフォーマットに切り替えた方がいい場面も多くあります。Lighthouseでいうと、「次世代フォーマットでの画像の配信」という項目で指摘されるやつですね。
次世代フォーマットでの画像の配信
これは実質「WebPとかAVIFくらいは使いなよ〜」というやつです。
WebPはなんだかんだで登場してから長いので、なんとなくは存在は知っていました。本記事の本筋ではないので、詳細は省きます。これ読んでください。
cwebp
コマンドで気軽に変換できるので、用意するのも簡単でした。
一方、最近まで恥ずかしながら全く知らなかったのがAVIFです。AVIF(AV1 Image File Format)はHEIF技術をベースにしたフォーマットで、iPhoneなどで使われているHEICの親戚に当たるものです。圧縮効率が高く、軽量で高画質な画像を提供できるということで、最近のブラウザで対応が進んでいます。
次の記事を読むと、AVIFについて色々と検証されていて興味深いです。
また、caniuseを見てみると、2024年6月現在、主要ブラウザでは対応が済んでいるみたいですね。
AVIFの対応状況
AVIFへの変換には、僕はたまたま見つけたsquooshを使っています。
オープンフォーマットということもあって、いろんな選択肢がありそうですね。
もともと1.4MBあったJPEG画像をsquooshでAVIF変換してみたのですが、次のような結果になりました。
- Quality 50%(ほぼ画質に遜色なし)→ 114kB
- Quality 30%(やや粗くなる)→ 57.3kB
Quelity 30%で元の3%までサイズが減った
実用上はQuality 50%で綺麗すぎるくらいなので、これでいいかなと思っています。
AVIFやWebPを使う
というわけで、画像のフォーマットも切り替えてみましょう。画像の表示には<picture>
要素を使います。<picture>
要素は、複数の画像ソースを指定して、ブラウザが対応しているものを選んで表示することができます。
<picture>
<source type="image/avif" srcset="/images/sample.avif">
<source type="image/webp" srcset="/images/sample.webp">
<img src="/images/sample.jpg" alt="サンプル画像">
</picture>
<source>
要素でtype
属性にフォーマットを指定し、srcset
属性に画像のパスを指定します。上から順にブラウザの対応しているものがあれば採用し、もしなければ<img>
要素のsrc
属性で指定した画像を表示します。
解像度にも対応させたい場合は、次のように書きます。
<picture>
<source
type="image/avif"
srcset="/images/sample.avif 1x, /images/sample@2x.avif 2x"
>
<source
type="image/webp"
srcset="/images/sample.webp 1x, /images/sample@2x.webp 2x"
>
<img
src="/images/sample.jpg"
srcset="/images/sample.jpg 1x, /images/sample@2x.jpg 2x"
>
</picture>
これで、解像度に合わせて、かつブラウザの対応しているフォーマットで画像を表示することができます。
まとめ
適切な画像を表示できるようチューニングするには、なんらかのロジックを通さないといけないとは思っていたのですが、かなりの部分がHTMLのみの表現で実現できることがわかり、嬉しくなって記事を書いてしまいました。
source要素には、メディアクエリーで条件付けができる media
属性などもあり、さらに複雑な条件で画像を切り替えることもできるようです。
よりよいWeb表現のために、精進していきます。
Discussion