Web画像最適化の実務|WebP/AVIF選定からsrcset・lazyload・CLS対策まで

Webページの転送量の大半を占めるのは、多くの場合画像です。JavaScriptのチューニングに時間をかける前に画像を見直すほうが、体感速度への効果が大きいケースは珍しくありません。しかも画像最適化は、フォーマット・サイズ・読み込みタイミング・レイアウトという複数の観点が絡むため、場当たり的に対応すると抜け漏れが出ます。

本記事では、フォーマット選定、srcset/sizesによる出し分け、遅延読み込み、CLS対策としてのwidth/height指定という4つの実務ポイントを整理します。

目次

フォーマット選定|WebPを基本線に、AVIFを上乗せ

現在の主要フォーマットの位置づけは次のとおりです。

  • WebP: JPEG/PNGより高圧縮で、透過やアニメーションにも対応。主要ブラウザで広くサポートされており、現在の実務の基本線です
  • AVIF: WebPよりさらに圧縮率が高い次世代フォーマット。エンコードが重いため、ビルド時やCDNでの事前変換に向きます
  • JPEG/PNG: フォールバック用途。SVGはロゴ・アイコンなどベクター素材で第一候補

複数フォーマットの出し分けは <picture> 要素で行います。ブラウザは上から順に評価し、対応する最初のsourceを使います。

<picture>
  <source srcset="photo.avif" type="image/avif">
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" width="800" height="600" alt="説明">
</picture>

手作業での変換運用は続かないので、画像CDN(Accept ヘッダーを見て自動変換するタイプ)やビルドパイプラインへの組み込みで自動化するのが現実解です。

srcset/sizes|デバイスに合ったサイズだけを配る

スマートフォンに幅2000pxの画像を配信するのは帯域の無駄です。srcset で複数解像度の候補を渡し、sizes で「この画像はビューポートの何割で表示されるか」をブラウザに伝えると、ブラウザが最適な1枚を選択します。

<img
  src="photo-800.webp"
  srcset="photo-400.webp 400w, photo-800.webp 800w, photo-1600.webp 1600w"
  sizes="(max-width: 600px) 100vw, 50vw"
  width="800" height="600" alt="説明">

実務でつまずきやすいのは sizes の書き忘れです。省略すると100vw扱いになり、せっかく候補を用意しても大きめの画像が選ばれがちです。CSSでの表示幅と sizes の記述がずれていないかは、DevToolsで実際に選択されたリソースを確認して検証します。Next.jsの next/image のようなフレームワークの画像コンポーネントは、この生成を自動化してくれるため積極的に使ってよい部分です。

遅延読み込み|lazyloadの適用範囲を間違えない

画面外の画像は loading="lazy" を付けるだけでネイティブに遅延読み込みされます。JavaScriptライブラリを入れる必要は基本的にありません。

  • ファーストビューより下の画像には loading="lazy" を付ける
  • ファーストビュー内の画像、特にLCP候補には絶対に付けない。読み込み開始が遅れ、LCPが悪化します
  • LCP画像には逆に fetchpriority="high" で優先度を上げる
  • decoding="async" を併用するとデコードによるメインスレッドの占有を緩和できます

「テンプレートの画像タグ全部にlazyを一括付与したらトップページが遅くなった」というのは定番の事故です。適用範囲は表示位置で判断します。

width/height指定でCLSを防ぐ

画像の読み込み完了時にレイアウトがガタッとずれる現象は、CLS(Cumulative Layout Shift)としてCore Web Vitalsの評価を直接悪化させます。原因は、画像の読み込みが終わるまでブラウザが表示領域の高さを確保できないことです。

対策はシンプルで、img 要素に widthheight 属性を必ず指定することです。実寸で固定される訳ではなく、モダンブラウザはこの2つの値からアスペクト比を計算して領域を事前確保します。CSSで width: 100%; height: auto; を指定していても縦横比は維持されます。

img {
  max-width: 100%;
  height: auto; /* width/height属性のアスペクト比が使われる */
}

サイズが動的に決まる場合はCSSの aspect-ratio プロパティで比率を指定する方法もあります。いずれにせよ「画像が来る前に場所を確保しておく」のが原則です。

まとめ

Web画像最適化の実務は、(1) WebPを基本にAVIFをpicture要素で上乗せする、(2) srcset/sizesでデバイスに合ったサイズだけを配信する、(3) 画面外の画像だけをlazyloadし、LCP画像は逆に優先読み込みする、(4) width/height指定でCLSを防ぐ、の4点に集約されます。個別のテクニックとしてではなく、画像CDNやフレームワークの画像コンポーネントで仕組み化して「新しく追加される画像も自動的に最適化される」状態を作ることが、運用まで見据えた最適化です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

クラウド・バックエンドエンジニア。AWSを中心に設計・構築から運用までを担当しています。主要言語は Java・JavaScript・Python。運用の現場で拾った知見を、再現できる手順に落として残すのがこのブログのテーマです。

目次