【Webフォント最適化】pyftsubsetでInterとNoto Sans JPをサブセット化する手順

WordPress速度・SEO改善

Webフォントの読み込みが遅くて困っていませんか?

Webサイトの表示速度で気になるのが、フォントの読み込み時間です。特に日本語フォントはファイルサイズが大きく、サイト全体の初回表示が遅くなります。Google Fontsから読み込んでいるだけでは、表示速度の改善に限界を感じることもあるでしょう。

フォントを軽量化したいと思っても、専門的な知識がないとどこから手を付けていいか分かりません。検索すると「サブセット化」「pyftsubset」などの情報が出てきますが、コマンドライン操作に慣れていないと、手順を間違えてフォントが壊れてしまうのではと不安になります。

この記事では、Google Fontsから入手したInterとNoto Sans JPの可変フォントを、pyftsubsetというツールでサブセット化し、WordPress子テーマで使える軽量なWebフォント環境を作る方法を解説します。

要点サマリー

  • Interは英数記号のみ(ASCII+主要記号)に限定
  • Noto Sans JPは日本語担当で、仮名・記号・漢字(U+4E00-9FFF)を基本セットとして入れる
  • –no-hinting で両フォントのサイズを大幅削減
  • 出力はWOFF2で、子テーマの fonts に配置
  • ウェイトが少ないなら静的フォントのほうが効率的

基本の考え方

サブセット化とは、使う文字だけを残してフォントを小さくする方法です。英字はInter、和文はNoto Sans JPと役割を分けることで、表示が安定して軽くなります。

今回は子テーマにフォントを直接置いて読み込む方法を使います。CDNに頼らずpreloadやfont-displayを組み合わせると、読み込み速度を改善できます。

今回は可変フォントを例にしますが、もし本文で400、見出しで700といった限られたウェイトしか使わないなら、静的フォントを個別にサブセット化したほうがファイルはさらに小さくなります。用途に応じて選んでください。

実装手順

手順は準備→導入→Inter→Noto→組み込み→検証の流れで進めます。作業前にフォルダ構成を決めておくとスムーズです。

前提環境

作業用のフォルダを用意します。テーマを自作する人は少ないので、WordPress子テーマを前提に説明します。

  • ダウンロード元: Google Fonts
  • フォルダ例: project/fonts/source に元フォント、project/fonts/subset に出力
  • WordPress子テーマ: 子テーマ直下にfontsフォルダを作成

ダウンロードするファイル

  • Inter-VariableFont_opsz,wght.ttf
  • NotoSansJP-VariableFont_wght.ttf

Interは英数記号だけを使い、Noto Sans JPは日本語(仮名+漢字)を担当します。paltを残して自然な字間にします。

ウェイトが限られる場合は可変ではなく、400や700の静的フォントを個別にサブセット化したほうが小さくなることがあります。

Step0: フォントの取得と配置

やること

  • Google Fontsから上記2ファイルをダウンロード
  • project/fonts/source に置く
  • 子テーマにはまだ置かない(サブセット化後に配置)

ポイント

  • ファイル名はそのままにすると後で迷わない
  • 可変フォントは1ファイルで幅広い表現を扱える

Step1: pyftsubsetの準備

pyftsubsetはfonttoolsに含まれているサブセット化ツールです。導入にはpipxを使うと、Python環境を壊さずに済むのでおすすめです。WindowsとmacOSで手順が少し異なります。

Windowsの場合(PowerShell)

  1. Python 3が入っているか確認
py --version

未導入ならインストールします。

  1. pipxをインストール
py -m pip install --user pipx
py -m pipx ensurepath
  1. fonttoolsを導入
pipx install fonttools
  1. 動作確認
pyftsubset --version
where pyftsubset

バージョンが表示され、実行ファイルのパスが出れば準備完了です。

macOSの場合(Terminal, zsh)

  1. Python 3が入っているか確認
python3 --version

未導入なら公式インストーラーかHomebrewでPython3を入れます。

  1. pipxをインストール
brew install pipx
pipx ensurepath
  1. fonttoolsを導入
pipx install fonttools
  1. 動作確認
pyftsubset --version
which pyftsubset

バージョンが表示され、実行ファイルのパスが出れば準備完了です。

よくある失敗と対処

pyftsubsetが見つからない

新しいターミナルを開いて再度確認してください。

command not found: pipx

Homebrewが正しくインストールされているか確認するか、python3 -m pip install --user pipx で直接インストールしてください。

PATHが通っていない

pipx ensurepath を実行した後、一度ログアウトして再ログインしてください。

WOFF2出力でエラーが出る

fonttools側のWOFF2圧縮ライブラリが不足している場合があります。エラーメッセージに従って依存関係を追加し、再実行してください。

Step2: Interをサブセット化(英数記号のみ)

Interは英数記号だけを残して軽くします。Unicode範囲を指定する方法がシンプルです。よく使う記号(ダッシュや引用符など)を最初から含めておくと、後で文字化けして作り直す手間が減ります。

やること

cd project/fonts/source
pyftsubset "Inter-VariableFont_opsz,wght.ttf" \
  --output-file="../subset/Inter-Subset.woff2" \
  --flavor=woff2 \
  --no-hinting \
  --unicodes=U+0020-007E,U+00A0,U+2013,U+2014,U+2018,U+2019,U+201C,U+201D,U+2026

補足

  • 必要な記号があれば、U+コードをカンマで追加します
  • –no-hinting でヒンティング情報を削除し、サイズを大幅に削減できます(WOFF2 では視認性への影響が小さいことが多い)

内訳(InterのUnicodeレンジ)

  • U+0020-007E: 基本ラテン(ASCII)。半角英数と基本記号
  • U+00A0: ノーブレークスペース(改行しない空白)
  • U+2013: エンダッシュ(短いダッシュ)
  • U+2014: エムダッシュ(長いダッシュ)
  • U+2018, U+2019: 左右のシングルクォート
  • U+201C, U+201D: 左右のダブルクォート
  • U+2026: 省略記号(三点リーダー)

確認方法

subsetフォルダに Inter-Subset.woff2 が生成されていることを確認してください。実際にHTMLファイルを作って英数字が正しく表示されるかテストすると安心です。

Step3: Noto Sans JPをサブセット化(日本語+palt)

日本語フォントは文字数が多いので、「とりあえず困らない基本セット」を最初から入れておくのが安全です。仮名・句読点・全角/半角形に加えて、漢字(U+4E00-9FFF)も含めます。paltという字間調整機能も残しておきます。

やること(基本セットをレンジ指定)

cd project/fonts/source
pyftsubset "NotoSansJP-VariableFont_wght.ttf" \
  --output-file="../subset/NotoSansJP-Subset.woff2" \
  --flavor=woff2 \
  --no-hinting \
  --unicodes=U+3000-303F,U+3040-309F,U+30A0-30FF,U+31F0-31FF,U+FF00-FFEF,U+4E00-9FFF \
  --layout-features=ccmp,locl,kern,palt

補足

この設定だと漢字が多く含まれるため、フォントファイルは大きくなります。もっと軽くしたい場合は、次の「上級:実際に使う文字だけに絞る」の方法を試してください。

上級:実際に使う文字だけに絞る(軽量化を優先したい場合)

サイトで実際に使う文字(サイト名、見出し、本文、ボタンなど)を chars.txt にまとめて、--text-file オプションでサブセット化する方法です。ファイルサイズを最小限にできます。

cd project/fonts
cat > chars.txt << 'EOF'
サイト内で使う日本語テキストを貼り付ける
EOF
cd project/fonts/source
pyftsubset "NotoSansJP-VariableFont_wght.ttf" \
  --output-file="../subset/NotoSansJP-Subset.woff2" \
  --flavor=woff2 \
  --no-hinting \
  --text-file="../chars.txt" \
  --layout-features=ccmp,locl,kern,palt

文字が欠けたら、欠けた文字を chars.txt に追加して再出力します。

保持しているOpenType機能(–layout-features=ccmp,locl,kern,palt)

  • ccmp: 合成/分解の正規化で字形崩れ防止
  • locl: 言語別のローカライズ字形を選択
  • kern: ペアカーニングで間隔を微調整
  • palt: プロポーショナル代替で約物やカナの字間を整える

ポイント

基本セット(レンジ指定)は設定が簡単ですが、ファイルサイズは大きくなります。もっと削りたい場合は --text-file を使って、文字が欠けたら chars.txt に追加して再出力する流れになります。

確認方法

サンプルHTMLで自然な字間と欠け文字がないこと

Step4: 子テーマに配置し、@font-faceで読み込む

出力したWOFF2を子テーマに置き、CSSで読み込みます。Interは英数字、Notoは日本語の役割です。

やること

  • subsetフォルダの Inter-Subset.woff2 と NotoSansJP-Subset.woff2 を 子テーマ/fonts にコピー
  • 子テーマのstyle.cssやSCSSにフォント定義を記述

例(可変フォント)

@font-face {
  font-family: 'Inter';
  src: url('./fonts/Inter-Subset.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Noto Sans JP';
  src: url('./fonts/NotoSansJP-Subset.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
html { font-family: 'Inter', 'Noto Sans JP', system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif; }
body { font-feature-settings: 'palt' 1; }

上記は style.css が子テーマ直下、フォントが 子テーマ/fonts にある想定です。自分の環境に合わせて url() のパスを書き換えてください。

静的ウェイト例(400と700だけを使うなら静的ファイルをサブセット化したほうが効率的)

@font-face {
  font-family: 'Inter';
  src: url('./fonts/Inter-Subset-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('./fonts/Inter-Subset-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Noto Sans JP';
  src: url('./fonts/NotoSansJP-Subset-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Noto Sans JP';
  src: url('./fonts/NotoSansJP-Subset-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

ポイント

可変フォントは幅広いウェイトを使えて便利ですが、400と700だけしか使わないなら静的フォントのほうが軽くなります。

Interは英数字、Noto Sans JPは日本語という役割分担です。local() は省略しています(デバッグしやすいため)。

font-display は基本的に swap で問題ありません。フォント非表示時間を減らしたい場合だけ optional を検討してください。preloadはLCPに関わるフォントだけに絞ります。

確認方法

  • 英数はInter、和文はNotoで出る
  • ページ全体で文字化けがない

Step5: preloadの設定

体感をもっと良くしたいときは、LCPに関わるフォントだけを先に読ませます。

例(functions.php)

function child_preload_fonts() {
  $fonts = array(
    get_stylesheet_directory_uri() . '/fonts/NotoSansJP-Subset.woff2',
    get_stylesheet_directory_uri() . '/fonts/Inter-Subset.woff2',
  );
  foreach ( $fonts as $url ) {
    echo '<link rel="preload" href="' . esc_url( $url ) . '" as="font" type="font/woff2" crossorigin>' . "\n";
  }
}
add_action('wp_head', 'child_preload_fonts', 1);

ポイント

すべてのフォントをpreloadすると逆効果になります。LCP(最大コンテンツ描画)に関わるフォントだけに絞ってください。

【WordPress】Webフォントのちらつき(FOUT)を抑える実践ハック
WordPressでサイトを開いたとき、最初の数秒だけ文字が別のフォントで表示され、その後パッと切り替わる現象に気付いたことはありませんか?これはFOUT(Flash of Unstyled Text...

計測と検証

作業が終わったら効果を確認します。感覚だけでなく、ツールと実機でしっかり確かめましょう。

確認方法

  • PageSpeed InsightsでLCPとCLSを比較
  • Chrome DevToolsでフォント取得の順序と所要時間を確認
  • 実機で日本語の字間や英数字の表示をチェック

よくある失敗

  • サブセットが小さすぎて必要文字が不足する
  • paltを外して字間が不自然になる
  • preloadの入れすぎで他リソースが遅くなる

まとめ

  • Interは英数記号、Noto Sans JPは日本語という役割分担で軽量化
  • pyftsubsetで必要文字だけを残し、WOFF2で出力
  • paltを残して字間を自然にする
  • 子テーマに配置して読み込み、必要に応じてpreloadで前倒し
  • ウェイトが限られるなら静的フォントのほうが軽い
  • 計測と実機確認で効果を見てから本番適用

フォント最適化でお困りの方へ

コマンドライン操作やフォント設定に不安がある場合、代わりに対応することも可能です。

  • フォントのサブセット化と子テーマへの設置
  • preload設定とパフォーマンスチューニング
  • 実機での表示確認と微調整
  • 24時間以内に返信

WordPress子テーマのカスタマイズは得意なので、フォント周りで何かお役に立てられるかもしれません。環境に合わせて、安全に作業を進めることができます。

ココナラで相談する: https://coconala.com/services/31984

ゆう

Web屋10年以上のフリーランス|WordPressとサイト改善が得意
いまはAIに夢中。仕事も暮らしもAI活用/個人開発も少し
株・ポイ活/子育て奮闘中。豆腐メンタルなので平和にいきたい
AI社会でも非デジタルを大切に。三度の飯とたこやきが好き

Follow Me
WordPress速度・SEO改善
タイトルとURLをコピーしました