このシリーズでは、まだまだ認知度の低いウェブサステナビリティの基本的な概念の説明や、ウェブ制作の現場において私たちが具体的にできることを紹介していきます。

前回の導入編では、インターネットにおける課題の現状認識と、ウェブサステナビリティの基本的な概念を説明したうえで、ウェブサステナビリティの取り組みを導入する一例を紹介しました。

今回は「メディア編」として、ユーザに情報を伝達する手段である画像と動画の、ウェブサステナビリティに関する改善策を考えていきます。

HTTP Archive による年次レポート「The 2022 Web Almanac」の「Sustainability」の章において、CO2 排出にもっとも影響しているのは、画像と JS であるとされています1

まずは、この画像に対する改善策を考えていきます。

画像の必要性を評価する

見出し「画像の必要性を評価する」

多くのウェブサイトにおいて、画像は必要不可欠な要素です。情報をわかりやすく伝達するためや、メンタルモデルを形成するため、感情に訴えかけるためなどに使用されます。

そのため、「ウェブデザインに画像は不要である」「表示速度を向上させるために妥協すべきだ」と主張したいわけではありません。そもそもユーザに興味を持ってもらったり、情報を伝える手助けをできなければ本末転倒です。

しかし、写真素材(ストックフォト)のような、関連性が低い画像の使用を考えているときには、再考の余地がありそうです。

そのページを構成する要素として、ユーザにとって本当に必要な要素なのか、よりパフォーマンスに優れた他の表現方法がないかを考えたうえで、画像の必要性を評価することが求められます。

遅延読み込みを指定する

見出し「遅延読み込みを指定する」

最初に表示されるビューポートよりも下に配置されている画像要素(<img>)には、遅延読み込み(loading="lazy")を指定します。

スクロールして表示される画像要素には loading="lazy" を指定する
<!-- ❌ Bad -->
<img src="..." alt="..." width="800" height="600">

<!-- 👍 Good -->
<img src="..." alt="..." width="800" height="600" loading="lazy">

この指定によって、表示速度が改善するとともに、ユーザがスクロールの下に隠れている画像を見ることなく別のページに移動したときに、それらのファイルを読み込むコストが削減できます。

HTTP Archive による画像に関する統計データ2によると、2024 年 8 月 1 日時点で、画像にブラウザネイティブの遅延読み込み(loading="lazy")が指定されている割合は、モバイルで 32.9%、デスクトップで 32.8% と、全体的にはまだまだ少ない状況です。

JS を使用した遅延読み込み

見出し「JS を使用した遅延読み込み」

前述のデータでは、JS で実装している場合は除外されているので、画像に対して遅延読み込みが指定されている割合は、実際のところはもっと多いはずです。

しかし、JS で実装する場合には、いくつかの欠点があります。

  • 画像ファイルがブラウザの Preload Scanner の対象外になる3
  • JS ファイルを読み込んで、解析して、実行するコストが上乗せされる
  • JS ファイルが正しく読み込まれなかったり、スクリプトにエラーが発生すると、最悪のケースでは画像が表示されなくなる

Preload Scanner とは、メインの HTML パーサが構文解析している間に、同時並行して必要なサブリソースを見つけ出して、投機的に先読みするブラウザの機能です。

これらの点を踏まえると、特別な理由がない限り JS での実装は避け、ブラウザネイティブの loading="lazy" を使用したほうがよいでしょう。

Fetch Priority API を使用する

見出し「Fetch Priority API を使用する」

前項の遅延読み込みで気をつける点としては、LCP の候補となるような、ファーストビュー(Above the fold)に表示される画像に loading="lazy" を指定しないことです。

これらの画像を遅延読み込みさせると、ランディング時のパフォーマンスが悪くなり、ユーザ体験が悪化し、LCP のスコアも下がってしまいます。

ファーストビューに表示される画像には lodading="lazy" を指定するのを避け、代わりに fetchpriority="high" を指定して、優先度が高いリソースであることをブラウザに伝えるとよいでしょう。

優先度の高い画像に fetchpriority を指定する例
<img src="..." alt="..." width="800" height="600" fetchpriority="high">

また、ファーストビューにカルーセルの UI を表示するようなケースでは、最初に表示される画像以外に fetchpriority="low" を指定して、優先度を下げることが望ましいです。

カルーセルそのものの是非については、別途取り上げたいと考えています。

カルーセルに fetchpriority で優先度をつける例
<ul class="carousel">
  <!-- 最初に表示される画像の優先度を上げる -->
  <li><img src="..." alt="..." width="800" height="600" fetchpriority="high"></li>

  <!-- 最初に隠れている画像の優先度を下げる -->
  <li><img src="..." alt="..." width="800" height="600" fetchpriority="low"></li>
  <li><img src="..." alt="..." width="800" height="600" fetchpriority="low"></li>
</ul>

同様に、ファーストビューに複数の画像が配置されている場合には、相対的な優先度を高めるために、LCP の候補となる画像のみに fetchpriority="high" を指定するのがよいでしょう。

2024/09/02 追記

LCP の要因は以下の 4 つのサブパート(カテゴリ)に分類できます。

Time to First Byte(TTFB)

リクエストの開始から、メインリソース(HTML ドキュメント)の最初のバイトを受信するまでの時間

Resource load delay

TTFB から LCP リソースの読み込みが開始されるまでの時間

Resource load duration

LCP リソースの読み込みが開始してから完了するまでの時間

Element render delay

LCP リソースの読み込みが完了してから、要素が描画されるまでの時間

LCP の 4 つのサブパートのタイムラインをウォーターフォールチャートに示した図
Optimize Largest Contentful Paint | web.dev を元に作成

前述の fetchpriority="high" は、LCP 候補の画像をいち早く読み込ませる施策なので、2 番目の Resource load delay のみに効果があります。

つまり、他のカテゴリに LCP のボトルネックが存在する場合、別の角度からアプローチする必要があります。例えば、原因が TTFB にある場合には、ホスティング環境や、サーバサイドの処理などを見直す必要があるかもしれません。

最新の画像フォーマットを使用する

見出し「最新の画像フォーマットを使用する」

画像フォーマットを選択するには、おもに以下の 3 つの点から検討します。

  1. 圧縮(ファイルサイズ)
  2. 品質
  3. エンコード・デコードの速度

比較的新しい画像フォーマットである WebP と AVIF は、すでに主要なブラウザではサポートされており、品質を損なうことなく、従来の JPEG や PNG よりも軽量化することができます。

相互運用性の観点からは、Safari が AVIF をサポートしたのは、iOS では 16.0 からなので、それよりも前のバージョンをフォローするには、<picture> 要素を使用して、フォールバック用の画像とともに実装するとよいでしょう。

<picture> 要素で複数のフォーマットの画像を指定する例
<!-- AVIF に非対応の環境では JPEG が使用される -->
<picture>
  <source type="image/avif" srcset="photo.avif">
  <img src="photo.jpg" alt="代替テキスト" width="800" height="600">
</picture>

ここで注意する点としては、必ずしも新しいフォーマットが優れているというわけではなく、画像の内容や、ユーザの閲覧環境によっては、JPEG や PNG のようなレガシーなフォーマットのほうが適しているケースもありえるということです。

例えば、品質とファイルサイズ(圧縮)の観点だけで考えると、AVIF が優れていることが多いですが、デコード時に漸進的に画像を表示することができません4

そのため、画像のサイズが大きい場合や、通信速度が不安定な場合には、画像が表示されるまでの間、その領域には何も表示されません。

WebP と AVIF の画像のデコードの違いを表す図。WebP では画像は上から下に漸進的に読み込まれる(incremental)に対し、AVIF では画像はゼロの状態から一気に表示される(all-or-nothing)
Image taken from British Library

また、WebP と AVIF は、JPEG におけるプログレッシブや、PNG におけるインタレースのように、読み込み状況に応じて徐々に解像度を上げていくデコード方法は用意されていません。

これらの点を踏まえて、基本は最新の画像フォーマット(WebP や AVIF)としつつ、サイトの共通要素やヒーローイメージ(メインビジュアル)のような重要な画像や、頻繁にリクエストが発生する画像に対しては、各フォーマットや書き出し品質を比較して、クオリティとパフォーマンスの最適なバランスを模索してもよいかもしれません。

WebP と AVIF はそれぞれ、動画のコーデックである VP8 と AV1 から派生したのに対して、JPEG XL は、JPEG の次世代フォーマットとして誕生した、純粋な画像のためのフォーマットです。

JPEG XL は、すでに ImageMagick のようなイメージライブラリや、Adobe Camera Raw のような画像編集ソフトでサポートされていますが、主要ブラウザでの相互運用性については雲行きが怪しい状況です。

具体的には、2022 年 12 月、曖昧な根拠によって Google Chrome(Chromium M110)から JPEG XL の実験的な機能が削除され、Interop 2024 の候補からも外された経緯から、Google Chrome でのサポートは厳しいように思えます。

一方で、JPEG XL は Safari 17 からサポートされたので、<picture> 要素で実装すれば、フォールバック画像とともに使用することは可能です。

JPEG XL をフォールバック画像とともに使用する例
<picture>
  <source type="image/jxl" srcset="photo.jxl">
  <source type="image/avif" srcset="photo.avif">
  <img src="photo.jpg" alt="代替テキスト" width="800" height="600">
</picture>

これは特に、iOS ユーザの多いサイトでは効果が見込め、ファイルの転送量の削減や、プログレッシブデコード5の恩恵を受けることができます。

その反面、画像配信サービスを使用しない限り、メンテナンスやエンコードの負担が増え、サーバに保存する画像の数(総ファイルサイズ)が増大する点も課題となります。

インライン SVG や CSS で表現する

見出し「インライン SVG や CSS で表現する」

構成要素が少なく、境界線が明確なグラフィックには、SVG が適しています。例えば、以下のようなタイプの画像には SVG 形式での実装が検討できます。

  • ロゴ
  • アイコン・ピクトグラム
  • シンプルなイラスト
  • チャート

SVG は、他の画像フォーマットと同じように、<img> 要素の src 属性にファイルパスを指定して読み込むこともできますが、HTML にインラインで直接埋め込むことで、データ転送のコストを削減することができます。

インライン SVG の例
<svg viewBox="0 0 27 27" width="27" height="27" role="img">
  <title>...</title>
  <path d="M20.035 13.5 13.5..."/>
</svg>

ただ、内容によっては、他の画像フォーマットで書き出した方がよいケースもあります。

例えば、書き出し元の画像のシェイプやアンカーポイントの数が多いために、ファイルサイズが大きくなってしまったり、SVG フィルタが多用されていることで、CPU に負荷がかかるといったことも考えられます。

この場合には、別のフォーマットで画像ファイルとして書き出して <img> 要素で読み込ませたほうが、最終的なコストは抑えられることもあります。

SVG の詳細については、以下の記事でも取り上げています。


その他の選択肢としては、CSS で表現する方法があります。

例えば clip-path プロパティを使用することで、SVG のようなシェイプでクリッピングできるので、簡単な図形であれば CSS のみで表現することも可能です。

clip-path プロパティの例
.icon-arrow::after {
  content: '';
  display: block;
  inline-size: 27px;
  block-size: 27px;
  clip-path: path('M20.035 13.5 13.5...');
  background-color: green;
}

これによって、SVG 同様にデータ転送のコストを削減することができますが、CSS のみによるグラフィックの表現は、基本的には装飾的な要素に限定したほうがよいでしょう。

画像を適切なサイズで書き出す

見出し「画像を適切なサイズで書き出す」

ウェブページのレイアウトに合わせて、画像を適切なサイズで書き出すことは、ウェブサステナビリティにおける観点からも、パフォーマンスの観点からも重要です。

レイアウトに対して小さく書き出すと、画像の輪郭が曖昧で粗い印象を与えますが、当然ながらファイルサイズは小さくなります。一方で、レイアウトに対してより大きな画像で書き出すと、シャープで精細な印象になりますが、その分ファイルサイズが大きくなります。

現在では、レスポンシブウェブデザインが主流であり、コンテンツのサイズはビューポートに応じて動的に変化します。加えて、デバイスによってピクセル比(DPR)も異なるため、書き出すサイズを決めるのは容易ではありません。

さらに、フォールバックするための、画像フォーマットのパターンまで含めると、画像の書き出しだけで途方もない労力が必要になります。

例えば、AVIF 形式の画像 3 サイズ、フォールバック用の JPEG 形式の画像 3 サイズの計 6 ファイルを、1 つの画像に対して指定する場合、以下のようなコードになります。

レスポンシブイメージの実装例
<picture>
  <!-- AVIF 形式の画像 3 サイズ -->
  <source
    type="image/avif"
    srcset="
      photo-400.avif 400w,
      photo-800.avif 800w,
      photo-1200.avif 1200w
    "
    sizes="
      (min-width: 1200px) calc(33.33vw - 40px),
      (min-width: 768px) calc(50vw - 30px),
      calc(100vw - 40px)
    "
  >
  <!-- フォールバック用の JPEG 形式の画像 3 サイズ -->
  <img
    src="photo-1200.jpg"
    alt="代替テキスト"
    width="400"
    height="400"
    srcset="
      photo-400.jpg 400w,
      photo-800.jpg 800w,
      photo-1200.jpg 1200w
    "
    sizes="
      (min-width: 1200px) calc(33.33vw - 40px),
      (min-width: 768px) calc(50vw - 30px),
      calc(100vw - 40px)
    "
    loading="lazy"
  >
</picture>

このコードを、画像ごとに直接指定していくのは現実的ではありません。

幸いにも、最近のフレームワークや CMS には、これらの画像を自動的に生成する機能が用意されているので、あとはサイトの条件やレイアウトのパターンに応じて、書き出す画像の種類や、sizes 属性の値を調整することで対応できます。

注意する点としては、パターン数を増やすと HTML のコード量が増大するので、パフォーマンスにも悪影響を及ぼします。加えて、エンコードする作業の負担や、アップロード時の転送量、サーバの容量などにも影響するため、適切なバランスを見定める必要があります。

レスポンシブイメージの詳細については、以下の記事でも取り上げています。

動画は、画像と比べると出現頻度こそ少ないですが、ファイルあたりの影響度が大きなメディアファイルであり、採用数も増加傾向にあります6

続いては、この動画に対する改善策を考えていきます。

本記事では、セルフホストする動画の <video> 要素を使用した埋め込みのみを対象とします。YouTube のようなサードパーティ製の動画の埋め込みについては、別途取り上げたいと考えています。

動画の必要性を評価する

見出し「動画の必要性を評価する」

まずは、そのページに動画が必要な要素なのかを評価します。

もちろん、前述した画像と同様、必要な動画まで削除する必要はありません。サービス内容や企業のメッセージを伝える動画や、チュートリアル動画、学習コンテンツの動画といったように、その目的が明確に説明できる動画であれば、有効活用すべきです。

しかし、動画を採用する理由が、「競合他社や参考にしたサイトが載せているから」、または「見栄えがよくなるから」といった場合には、本当にその動画が必要なのかを、ユーザ視点に立って再検討する余地がありそうです。

動画の自動再生を避ける

見出し「動画の自動再生を避ける」

サステナビリティとアクセシビリティの両方の観点から、動画の自動再生(autoplay)は、原則避けたほうがよいでしょう。

代わりに controls 属性を追加し、ユーザが自由に動画を制御できるようにします。

動画の自動再生を避ける
<!-- ❌ Bad -->
<video src="..." width="800" height="600" autoplay></video>

<!-- ✅ OK -->
<video src="..." width="800" height="600" controls></video>

サステナビリティの観点

見出し「サステナビリティの観点」

まず、サステナビリティの観点からは、ファイルサイズの大きな動画ファイルの場合、エネルギーの消費量が増大します。通信速度が不安定な場合には、この動画ファイルの読み込みに帯域が占領されてしまうかもしれません。

また、動画が自動再生されることで、通信量やバッテリーが多く消費されるので、とりわけモバイルユーザにとっては死活問題です。同時に CPU にも負担をかけるため、デバイス自体の寿命を縮めることにもなります。これらは結果的にユーザビリティを悪化させる要因にもなります。

さらに、autoplay 属性を追加すると、ファーストビューの外側に配置された動画であっても、ページ読み込みと同時にファイルの読み込みが開始されてしまいます。そのため、動画を見ることなく別のページに遷移した場合に、無駄なエネルギーを消費することになります。

アクセシビリティの観点

見出し「アクセシビリティの観点」

アクセシビリティの観点からは、WCAG の「2.2.2 一時停止、停止、非表示(レベル A)」の達成基準が該当します。この達成基準は「非干渉」の適合要件なので、基準に満たない場合、ページ全体の利用を妨げる可能性があります。

動き、点滅、スクロール

動きのある、点滅している、又はスクロールしている情報が、(1) 自動的に開始し、(2) 5 秒よりも長く継続し、かつ、(3) その他のコンテンツと並行して提示される場合、利用者がそれらを一時停止、停止、又は非表示にすることのできるメカニズムがある。ただし、その動き、点滅、又はスクロールが必要不可欠な動作の一部である場合は除く。

達成基準 2.2.2 一時停止、停止、非表示 | WCAG 2.1 解説書

一時停止ボタンを用意すれば基準自体は満たせますが、ユーザがボタンを認識して選択するまではデータの転送は続いているので、ユーザ中心のデザインとは言い難いかもしれません。

もし、自動再生を一時停止するボタンを用意する場合には、フィッツの法則7を踏まえて、ターゲットサイズを十分な大きさにし、認識しやすく、選択しやすい位置に配置し、周囲に十分な間隔を設けるようにしましょう。

しかし、キーボードのみで操作する場合や、スクリーンリーダーを使用して操作する場合のように、さまざまな文脈や状況で考えると、選択しやすい位置に配置すること自体、難易度が高いように思えます。

また、上記の達成基準とは別に「2.3.1 3 回の閃光、又は閾値以下(レベル A)」についても気をつける必要があります。こちらの達成基準も「非干渉」の適合要件です。

3 回の閃光、又は閾値以下

ウェブページには、どの 1 秒間においても 3 回を超える閃光を放つものがない、又は閃光が一般閃光閾値及び赤色閃光閾値を下回っている。

達成基準 2.3.1: 3 回の閃光、又は閾値以下 | WCAG 2.1 解説書

このように、動画の自動再生は、負担やリスクの大きいコンテンツであることを理解すると、できるだけ避けるべきデザインパターンだということがわかります。

動画のサイズを削減する

見出し「動画のサイズを削減する」

動画を書き出すときには、最低限の品質を確保しつつ、なるべく小さなファイルサイズになるように調整することが求められます。考えられる施策としては以下のとおりです。

  • 重要度の低いシーンをカットして、できるだけ短く簡潔にする
  • 最新のコーデックを使用する
  • 動画の解像度(縦横サイズ)を調整する
  • 品質の設定を調整する
  • フレームレート(FPS)を調整する
  • 音声が必要なければ、オーディオトラックを削除する

これらの項目をどの程度調整するかは、動画の内容によって異なるので、ここではコーデックの説明のみにとどめます。

コーデックとは、データをエンコード・デコードするプログラムである、エンコーダ・デコーダをブレンドした用語(混成語、かばん語)です。動画ファイルには映像データと音声データが含まれていますが、それぞれコーデックの種類が異なります。

映像のコーデック
コーデック正式名称コンテナのサポート(抜粋)
AV1AOMedia Video 1WebM、MP4
VP9Video Processor 9WebM、MP4
AVC(H.264)Advanced Video CodingMP4
HEVC(H.265)High Efficiency Video CodingMP4
音声のコーデック
コーデック正式名称コンテナのサポート(抜粋)
OpusOpusWebM、MP4
VorbisVorbisWebM
AACAdvanced Audio CodingMP4

この映像と音声の 2 つのコーデックに、動画のメタデータを加えたデータを格納するフォーマットはコンテナと呼ばれ、WebM や MPEG-4(MP4)などのフォーマットが該当します。

動画を最適化するには、ウェブに特化したフォーマットである、WebM をコンテナとして選択するのがよさそうですが、iOS Safari がサポートしたのが 17.4 から8なので、それ以前のブラウザも視野に入れる場合は、フォールバック用のフォーマットを指定する必要があります。

動画に WebM とフォールバック用の MP4 を指定する例
<video width="800" height="600" controls>
  <source type="video/webm" src="video.webm">
  <source type="video/mp4" src="video.mp4">
</video>

加えて、コンテナのサポートとは別に、コーデックのサポートがブラウザによって異なるので注意が必要です。

さらに、ウェブサイトに埋め込む動画の場合は問題ないですが、AVC(H.264)や HEVC(H.265)のように特許が設定されていることもあるため、念のため確認したほうがよいでしょう。

筆者は動画制作に関する専門性を持ち合わせていないため、この記事ではこれ以上は踏み込みませんが、ウェブページに動画を掲載するということは、動画をエンコードするだけでも検討項目が多く、非常に労力を要する作業であることがわかります。

動画のプリロードを無効にする

見出し「動画のプリロードを無効にする」

自動再生を無効にした場合、動画のデータを先読みする必要性は低くなるので、可能な限り preload="none" を指定します。

preload の指定はブラウザへのヒントに過ぎないので、最終的な挙動はブラウザに委ねられます。

動画に preload 属性を指定する例
<video src="..." width="800" height="600" preload="none" controls></video>

なお、preload="metadata" を指定したときには、動画のメタデータが先読みされ、最初のフレームがポスターフレーム(静止画)として表示されますが、preload="none" を指定すると、ポスターフレームは表示されません。

そのため、動画の最初のフレームを静止画として書き出して、poster 属性に指定します。

動画に poster 属性を指定する例
<video src="..." poster="./video.webp" width="800" height="600" preload="none" controls></video>

このポスター画像も、パフォーマンスに影響するので、できるだけ軽量にしたいのですが、レスポンシブイメージのように複数の画像は指定できないので、広くサポートされている形式を指定します。

また、現時点では、ポスター画像の遅延読み込み(loading="lazy")はできません9。動画に指定した preload="metadata" よりも重くなるようでは本末転倒なので、状況に応じて使い分けるとよいでしょう。

ビューポートに応じて動画を出し分ける

見出し「ビューポートに応じて動画を出し分ける」

例えばモバイルとデスクトップのレイアウトで、動画の解像度が大きく異なる場合には、それぞれ別のサイズで書き出し、media 属性を使用して出し分けることもできます。

ビューポート幅に応じて動画を出し分ける例
<video width="800" height="600" controls>
  <source type="video/webm" src="desktop.webm" media="(min-width: 800px)">
  <source type="video/mp4" src="desktop.mp4" media="(min-width: 800px)">
  <source type="video/webm" src="mobile.webm">
  <source type="video/mp4" src="mobile.mp4">
</video>

これにより、特にモバイルデバイスで閲覧したときに、必要以上に大きなファイルサイズの動画を読み込ませることを回避できます。

しかし、この手法では、最初に読み込まれたときの条件で表示される動画が固定化されてしまうので注意が必要です。つまり、最初に条件が確定すると、ビューポート幅を変更しても、別の動画に動的に切り替わることはありません。切り替えるには再読み込みする必要があります。

また、widthheight の属性は <source> 要素には指定できないので、アスペクト比が異なる場合には指定自体を外したほうがよいかもしれません。

レスポンシブイメージと同様に、パターン数によって書き出す動画のファイル数も増えるので、エンコードする作業の負担や、アップロード時の転送量、サーバの容量などを考慮しつつ、戦略を考える必要があります。

この記事では、ウェブサステナビリティにおける、画像と動画の改善策を紹介しました。

サステナビリティに配慮したウェブサイトを構築することによって、パフォーマンス最適化やアクセシビリティの向上が見込めますが、その逆もまた同様であるということがわかります。

もちろん、ここで紹介した改善策が適用できない状況もありますし、網羅されているわけでもないですが、サイト改善に取り組むきっかけになれば幸いです。

次回も、また別のテーマで、ウェブサステナビリティに関する改善策を取り上げる予定です。

本記事の作成にあたり、以下のウェブページを参考にしました。

脚注

  1. Sustainability | The 2022 Web Almanac

  2. State of Images | HTTP Archive

  3. Don’t fight the browser preload scanner | web.dev

  4. AVIF has landed | Jake Archibald

  5. Progressive Image Decoding Delivers an Enhanced Web Experience | Cloudinary

  6. Media | The 2022 Web Almanac

  7. Fitts’s Law | Laws of UX

  8. WebKit Features in Safari 17.4 | WebKit

  9. Lazy loading video element poster attribute | Issue #6636 | whatwg/html