コーポレートサイトの SEO チェックをしたところ、PageSpeed Insights で「画像配信を改善する」という指摘が多く出ました。原因を調べると、表示幅が 300px ほどの写真に 3000×2000px の元画像がそのまま使われていたり、ニュース記事に 3000px の写真がフルサイズで挿入されていたりしました。

クライアントが自分で記事を書くサイトでは、どんな大きさの画像がアップロードされても、表示する幅に合ったサイズで表示される仕組みが必要です。この記事では、WordPress のテーマ側で行っている画像管理の設定をまとめます。

アップロードした画像の縮小・圧縮・WebP 変換は、プラグイン「EWWW Image Optimizer」で行っています。プラグインの設定は「EWWW Image Optimizerの設定|無料版で画像を自動圧縮・WebP化する手順」にまとめました。

EWWW Image Optimizerの設定|無料版で画像を自動圧縮・WebP化する手順 | CODE-PLUS(コードプラス) WordPressの画像最適化プラグイン「EWWW Image Optimizer」を無料版で使うときの設定を、タブごとに画面つきで解説します。最大画像サイズ2560px、ピクセルパーフェクト圧縮、WebP変換とリライトルールの設定、有料の「簡単I...  続きを読む

全体の流れ

画像は、次の3段階で管理しています。

段階 担当 内容
アップロード時 EWWW Image Optimizer 長い辺を 2560px までに縮小し、圧縮と WebP の作成を行う
サイズの生成 テーマ(functions.php) 本文用(1200px)と一覧用(768px)などの縮小版を作る
挿入・表示 テーマ(functions.php)と WordPress 本体 本文には「大(1200px)」で挿入し、srcset で画面に合ったサイズを表示する

画像サイズの登録

WordPress は、画像をアップロードするたびに、登録されているサイズの縮小版を作ります。初期状態では、使わないサイズまで作られるので、テーマ側で整理しています。

//アイキャッチの有効化
add_theme_support('post-thumbnails');

//アイキャッチ・サムネイル画像サイズの設定
function mythumbnails_setup() {
  //アイキャッチサイズを作成しない
  add_image_size('medium', 0, 0);
  add_image_size('1536x1536', 0, 0);
  add_image_size('2048x2048', 0, 0);
  add_image_size('et-pb-post-main-image', 0, 0);
  add_image_size('et-pb-post-main-image-fullwidth', 0, 0);
  add_image_size('et-pb-portfolio-image', 0, 0);
  add_image_size('et-pb-portfolio-module-image', 0, 0);
  add_image_size('et-pb-portfolio-image-single', 0, 0);
  add_image_size('et-pb-gallery-module-image-portrait', 0, 0);
  //アイキャッチサイズを追加する
  add_image_size('thumbnail', 300, 300, true); //管理画面メディア一覧用, true = 切り抜く
  add_image_size('medium_large', 768, 0);      //一覧用, 0 = 高さ無制限
  add_image_size('large', 1200, 0);            //本文用, 0 = 高さ無制限
}
add_action('after_setup_theme', 'mythumbnails_setup');

幅と高さに 0 を指定したサイズは作られません。et-pb- で始まるサイズは、以前使っていたテーマ(Divi)が登録していたものです。テーマを替えても設定が残っていることがあるので、まとめて止めています。

残すのは、次の3つだけです。

サイズ名 大きさ 用途
thumbnail 300×300(切り抜き) 管理画面のメディア一覧
medium_large 幅 768px 一覧ページ
large 幅 1200px 記事の本文

「設定 › メディア」の数値は使わない

add_image_size() で登録したサイズは、管理画面の「設定 › メディア」の数値より優先されます。画面の数値を変えても反映されないので、迷わないように画面に案内を出しています。

//メディア設定画面に、画像サイズをテーマ側で管理している旨を表示する
function media_settings_notice() {
  $screen = get_current_screen();
  if (!$screen || $screen->id !== 'options-media') return;

  echo '<div class="notice notice-info"><p>'
     . '画像サイズは <code>themes/zaratan/functions.php</code> の <code>mythumbnails_setup()</code> で管理しています。'
     . 'この画面の数値を変更しても反映されません。'
     . '</p></div>';
}
add_action('admin_notices', 'media_settings_notice');

2560px を超える画像は EWWW で縮小する

WordPress 本体は、2560px を超える画像をアップロードすると、元画像を残したまま -scaled という縮小版を作ります。この記事の構成では、EWWW の「最大画像サイズ」で元画像そのものを 2560px までに縮小するので、本体の機能は止めています。

//2560px以上の画像(scaled)の自動生成を停止
add_filter('big_image_size_threshold', '__return_false');

メディア挿入時の初期サイズを「大」に固定する

縮小版を作っても、記事に「フルサイズ」で挿入されると、2560px の画像が読み込まれます。実際に、ニュース記事の写真が size-full で挿入されていました。

WordPress は、メディアを挿入するときに前回選んだサイズを覚えていて、次回もそのサイズを初期値にします。一度でも「フルサイズ」を選ぶと、それ以降もフルサイズが選ばれたままになります。そこで、次の2つを組み合わせて、毎回「大(large)」から始まるようにしました。

//メディア挿入時の画像サイズを、毎回「大(large)」にする
add_filter('pre_option_image_default_size', function () {
  return 'large';
});

function reset_media_insert_size() {
  ?>
  <script>
  (function () {
    function resetImgSize() {
      if (typeof window.setUserSetting === 'function') {
        window.setUserSetting('imgsize', 'large');
      }
    }
    //管理画面を開いたとき
    resetImgSize();
    //メディアの追加画面(モーダル)を開くたび
    if (window.wp && wp.media && wp.media.view && wp.media.view.Modal) {
      var originalOpen = wp.media.view.Modal.prototype.open;
      wp.media.view.Modal.prototype.open = function () {
        resetImgSize();
        return originalOpen.apply(this, arguments);
      };
    }
  })();
  </script>
  <?php
}
add_action('admin_print_footer_scripts', 'reset_media_insert_size', 99);

pre_option_image_default_size は、WordPress の既定の挿入サイズ(image_default_size)を large に固定するフィルターです。「設定 › メディア」には、この値を変える項目がありません。

前回選んだサイズは、ユーザー設定の imgsize に保存されていて、既定値より優先されます。そこで、管理画面を開いたときと「メディアを追加」の画面を開くたびに、setUserSetting('imgsize', 'large') で「大」に戻しています。記事の作成中に別のサイズを選ぶことはできますが、次に画面を開いたときは「大」から始まります。

なお、幅が 1200px 未満の画像には「大」の縮小版が作られないので、その場合は WordPress が自動でフルサイズを使います。

srcset で画面に合ったサイズを表示する

本文に画像を挿入すると、WordPress は srcset と sizes を自動で付けます。ブラウザは、画面の幅と解像度に合わせて、srcset の中から、表示に足りる最小のサイズを選びます。

<img src="…/photo-1200x800.jpg"
  srcset="…/photo-1200x800.jpg 1200w, …/photo-768x512.jpg 768w, …/photo.jpg 2560w"
  sizes="(max-width: 1200px) 100vw, 1200px"
  class="size-large wp-image-123" …>

ここで重要なのは、sizes の上限です。「大」で挿入すると上限が 1200px になり、スマホでは 768px などの小さい画像が選ばれます。「フルサイズ」で挿入すると上限が 2560px になり、高解像度の PC では 2560px の画像が選ばれてしまいます。初期サイズを「大」に固定しているのは、このためです。

すでにフルサイズで挿入した画像は、挿入し直すか、本文の size-full を size-large に、画像の URL を -1200x800 などの縮小版に変えると、「大」と同じ扱いになります。

保存時に自動で付けている属性

テーマでは、投稿を保存するときに、本文の画像へ2つの属性を自動で付けています(content_save_pre フィルター)。

処理 内容 目的
キャッシュ対策の日時 画像 URL の末尾に ?ver=保存日時 を付ける(既存の ver= は付け直す) 画像を差し替えたとき、ブラウザやキャッシュに古い画像が残らないようにする
aspect-ratio 実際の画像の寸法から style="aspect-ratio:幅/高さ" を付ける 画像の読み込み前に表示領域を確保し、レイアウトのずれ(CLS)を防ぐ

そのため、本文を変えずに「更新」を押しただけでも、リビジョンには ver= の日時の差分が残ります。変更内容をリビジョンで確認するときは、この差分を除いて見ると、実際の変更がわかります。

画像のアスペクト比を自動計算・付与する | aspect-ratioが効かない原因とCLS対策 | CODE-PLUS(コードプラス) 画像のアスペクト比を自動計算・付与する | aspect-ratioが効かない原因とCLS対策 | CODE-PLUS(コードプラス) CSS aspect-ratioが効かない原因を押さえつつ、投稿保存時に実画像からアスペクト比(縦横比)を自動計算・自動付与し、SP/PCの出し分けまで手作業ゼロで維持する仕組み、CLS対策として無理なく運用するための実運用での使い方を解説します。  続きを読む 【WordPress】画像URLにクエリパラメータを保存時に自動付与|キャッシュ対策 | CODE-PLUS(コードプラス) 【WordPress】画像URLにクエリパラメータを保存時に自動付与|キャッシュ対策 | CODE-PLUS(コードプラス) WordPressで画像のキャッシュ対策として`?ver=`クエリを自動付与する方法を解説。`the_content`フィルター方式の限界と、`content_save_pre`でDBへ直接書き込む新方式の完全なコード、Better Search ...  続きを読む

テーマ内の画像は、表示幅の2倍を目安に縮小する

メディアライブラリを通さない、テーマの images フォルダの画像は、手作業で縮小します。目安は「サイト上の表示幅の2倍」です。高解像度の画面でも粗く見えず、それ以上大きくしても見た目はほとんど変わりません。

実際に縮小を試した結果です(作業用のコピーで試算)。

画像 元の大きさ 表示幅(PC/スマホ) 縮小後 容量
施工実績の写真(6枚) 3000×2000px 291px/303px 800×533px 計 2,783KB → 約680KB(約75%減)
写真を PNG で保存していた画像 980×700px 525px/303px 同じ大きさで JPG に変換 322KB → 150〜200KB
トップの背景写真 4000×2060px 1261px/360px 2560px に縮小 631KB → 514〜768KB(減らないことがある)

試してわかったことが2つあります。

  • 元の画像がすでに強めに圧縮されている場合は、縮小しても容量があまり減りません。保存し直すときの品質が元より高いと、かえって増えることもあります。縮小後の容量は、必ず元と比べます
  • PNG は、macOS の sips などで縮小しても最適化されないので、容量が増えることがあります。PNG は、ImageOptim などの最適化ツールを通すか、図であれば SVG にします

表示幅は、ブラウザの開発者ツールで画像を選び、表示されているサイズを見て確認します。PC とスマホでレイアウトが違うので、両方の幅で確認します。

最初の画面の画像は遅延読み込みしない

テーマでは、画像の遅延読み込みを JavaScript(class="lazy" と data-src 属性)で行っています。画面に近づいたときに、data-src の URL を src に入れて読み込む仕組みです。

この仕組みは、ページの最初の画面に表示される画像には使いません。HTML に本物の URL を書いておけば、ブラウザは HTML を読み込んだ直後に画像の取得を始められます。遅延読み込みの画像に fetchpriority="high" を付けても、JavaScript が src を入れるまで取得が始まらないので、効果はありません。

実際に計測したところ、最初の画面の画像は約 0.3 秒で取得が始まっていましたが、LCP(最も大きい要素が表示される時刻)は約 2.3 秒でした。原因は画像ではなく、ページ全体を覆う読み込み中の表示(スピナー)が、一定時間たつまで消えない作りだったことです。表示速度を見直すときは、画像だけでなく、こうした演出の待ち時間も確認します。

alt 属性の付け方

画像のサイズと合わせて、alt 属性も見直しました。

画像の種類 alt 例
内容のある写真 写真の内容を短く書く alt="管理しているオフィスビルの外観"
文字が書かれた画像(図表・数値・見出し) 画像の中の文字をそのまま書く alt="従業員数〇〇人、平均年齢〇〇歳…"
リンクの中の画像だけのボタン リンク先がわかる言葉 alt="募集要項・エントリー"
装飾の画像 空にする alt=""
画像がないときの代わりの画像 空にする alt=""(alt="NoImage" にしない)

数値やグラフが画像の中にしかないと、検索エンジンはその内容を読み取れません。表やグラフは、できれば HTML のテキストにし、すぐに直せないときは alt に中身を書きます。

まとめ

  • 画像サイズは functions.php で必要なものだけを登録し、「設定 › メディア」の数値は使わない
  • アップロード時の縮小(2560px)と圧縮は EWWW に任せる
  • メディア挿入時の初期サイズを「大」に固定し、本文の画像は 1200px を上限にする
  • テーマ内の画像は表示幅の2倍を目安に縮小し、縮小後の容量を必ず確認する
  • 最初の画面の画像は遅延読み込みせず、alt には画像の中身を書く

EWWW Image Optimizer の各タブの設定は、「EWWW Image Optimizerの設定|無料版で画像を自動圧縮・WebP化する手順」で画面つきで紹介しています。

関連記事

EWWW Image Optimizerの設定|無料版で画像を自動圧縮・WebP化する手順 | CODE-PLUS(コードプラス) WordPressの画像最適化プラグイン「EWWW Image Optimizer」を無料版で使うときの設定を、タブごとに画面つきで解説します。最大画像サイズ2560px、ピクセルパーフェクト圧縮、WebP変換とリライトルールの設定、有料の「簡単I...  続きを読む 画像のアスペクト比を自動計算・付与する | aspect-ratioが効かない原因とCLS対策 | CODE-PLUS(コードプラス) 画像のアスペクト比を自動計算・付与する | aspect-ratioが効かない原因とCLS対策 | CODE-PLUS(コードプラス) CSS aspect-ratioが効かない原因を押さえつつ、投稿保存時に実画像からアスペクト比(縦横比)を自動計算・自動付与し、SP/PCの出し分けまで手作業ゼロで維持する仕組み、CLS対策として無理なく運用するための実運用での使い方を解説します。  続きを読む 【WordPress】画像URLにクエリパラメータを保存時に自動付与|キャッシュ対策 | CODE-PLUS(コードプラス) 【WordPress】画像URLにクエリパラメータを保存時に自動付与|キャッシュ対策 | CODE-PLUS(コードプラス) WordPressで画像のキャッシュ対策として`?ver=`クエリを自動付与する方法を解説。`the_content`フィルター方式の限界と、`content_save_pre`でDBへ直接書き込む新方式の完全なコード、Better Search ...  続きを読む WordPressのLCP・TBTをプラグインのJS/CSS整理で改善した施策 | CODE-PLUS(コードプラス) WordPressのLCP・TBTをプラグインのJS/CSS整理で改善した施策 | CODE-PLUS(コードプラス) WordPressのPageSpeedスコアが17というかなり厳しい状態から、プラグインのJS/CSSの整理だけで57まで改善できました。特にTBT(Total Blocking Time)は5.1秒 → 170ms、LCPは6.45秒 → 2.3...  続きを読む