



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp









生徒Webサイトで日本語のカスタムフォントを使いたいんですけど、ファイルサイズが大きすぎて読み込みが遅くなってしまいます…どうすれば良いでしょうか?



よーく聞くんだぞ!Webフォントの最適化には「サブセット化」が非常に重要じゃ。今日はサブセット化の実装方法から限界、その他の最適化テクニックまで、詳しく解説するぞい!



ありがとうございます!よろしくお願いします!
美しいタイポグラフィは、Webサイトの印象を大きく左右します。しかし、特に日本語フォントは文字数が多いため、ファイルサイズが非常に大きくなり、ページの読み込み速度に深刻な影響を与えます。
本記事では、Webフォントのサブセット化と最適化の実践的な手法について、pyftsubsetを使った具体的な実装方法、サブセット化の限界と対処法、font-display・preload・WOFF2・可変フォントなどの高度な最適化テクニックまで、実装例を交えながら詳しく解説します。
「学習→案件獲得」につなげた受講生のリアルな体験談も公開中!
働き方を変えたい方にも響くストーリーです。
菅井さん
将来的への不安と子育てという背景から「副業」に挑戦しようと決意。独学からプログラミングの学習を開始していたが、WithCodeに出会い体験コースを受講。約4ヶ月の学習に取り組み、当初の目標であった卒業テスト合格を実現した。WithCode Platinumにて3件の案件を担当し、現在は副業だけでなく本格的に「フリーランス」として在宅で活躍していきたいと考えるようになる。
詳しくはこちらの記事をご覧ください。


菅井さんの主な制作実績はこちら


Webフォント(Web Fonts)は、サーバー上に配置されたフォントファイルをブラウザがダウンロードして表示する技術です。システムフォントに依存せず、デザイナーが意図した通りのタイポグラフィを実現できます。
主なWebフォント形式は以下の通りです:
| 形式 | 拡張子 | 特徴 | ブラウザ対応 |
|---|---|---|---|
| WOFF2 | .woff2 | 最高の圧縮率、最新の標準 | Chrome 36+、Firefox 39+、Safari 12+ |
| WOFF | .woff | 広く対応、圧縮済み | ほぼすべてのモダンブラウザ |
| TTF/OTF | .ttf/.otf | 非圧縮、ファイルサイズ大 | すべてのブラウザ |
| EOT | .eot | IE専用(レガシー) | IE6-11のみ |
2026年現在、WOFF2が最も推奨されるフォーマットです。主要ブラウザのシェア98%以上がサポートしており、TTFと比較して平均30-50%のファイルサイズ削減を実現します。
CSSの@font-faceルールを使用してWebフォントを読み込みます:
@font-face {
font-family: 'MyCustomFont';
src: url('/fonts/mycustomfont.woff2') format('woff2'),
url('/fonts/mycustomfont.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
body {
font-family: 'MyCustomFont', sans-serif;
}

Webフォントには、パフォーマンスとユーザー体験に影響を与える重大な課題があります。
日本語フォントが抱える最大の問題は、圧倒的なファイルサイズです:
一般的な日本語フォントには、以下の文字が含まれます:
この膨大な文字数により、ファイルサイズが巨大化します。
FOITとは、フォントの読み込みが完了するまでテキストが表示されない現象です。
ユーザーは白紙の画面を数秒間見ることになり、以下の問題が発生します:
FOUTは、フォント読み込み前に代替フォントで表示され、読み込み完了後にWebフォントに切り替わる現象です。
視覚的な違和感を与える問題:
実際のWebサイトにおけるWebフォントの影響:



確かに、日本語フォントを使ったサイトは読み込みが遅い気がします…これを解決する方法があるんですか?



そのために「サブセット化」という技術があるんじゃ!使用する文字だけを抽出してファイルサイズを劇的に削減できるぞい!





サブセット化とは何ですか?



うむ。サブセット化(Subsetting)とは、フォントファイルから必要な文字だけを抽出し、不要な文字を削除する技術のことじゃ!
フォントファイルには、グリフ(字形)データがテーブル形式で格納されています。サブセット化は以下の処理を行います:
実際のファイルサイズ削減効果:
| フォント種類 | 元のサイズ | サブセット後 | 削減率 |
|---|---|---|---|
| 日本語(常用漢字のみ) | 8.5 MB | 2.1 MB | 75%削減 |
| 日本語(500文字限定) | 8.5 MB | 300 KB | 96%削減 |
| 欧文(基本ラテン文字) | 150 KB | 30 KB | 80%削減 |
適切なサブセット化により、日本語フォントのファイルサイズを90%以上削減することも可能です。
サブセット化には、いくつかのアプローチがあります:
1. 常用漢字のみ(約2,000文字)
2. 実際の使用文字のみ(数百文字)
3. 用途別サブセット(見出し用・本文用)





サブセット化の実装方法を教えてください!



うむ。まずはpyftsubsetを使った方法じゃ。pyftsubsetは、Googleが開発したフォントサブセット化ツールで、最も強力で柔軟性の高いツールなのじゃ!
Pythonのパッケージ管理ツールpipを使用してインストールします:
# fonttools(pyftsubsetを含む)をインストール
pip install fonttools
# Brotli圧縮サポート(WOFF2生成に必要)
pip install brotliコマンドラインから実行する基本的な例:
# 特定の文字だけを抽出
pyftsubset input.ttf \
--text="あいうえおかきくけこ" \
--output-file=output.woff2 \
--flavor=woff2常用漢字リストを使用したサブセット化:
1. 常用漢字リストファイルを作成(joyo-kanji.txt):
# joyo-kanji.txt に常用漢字2,136文字を記載
# ひらがな、カタカナ、基本記号も含める
あいうえおかきくけこ...
アイウエオカキクケコ...
亜哀挨愛曖悪握...2. pyftsubsetコマンドを実行:
pyftsubset MyFont.ttf \
--text-file=joyo-kanji.txt \
--output-file=MyFont-subset.woff2 \
--flavor=woff2 \
--layout-features='*' \
--no-hintingパラメータの説明:
--text-file: 抽出する文字を含むテキストファイル--flavor=woff2: 出力形式(woff2が推奨)--layout-features='*': すべてのレイアウト機能を保持--no-hinting: ヒンティング情報を削除(ファイルサイズ削減)文字コードの範囲を指定して抽出:
pyftsubset MyFont.ttf \
--unicodes="U+0020-007E,U+3040-309F,U+30A0-30FF,U+4E00-9FFF" \
--output-file=MyFont-subset.woff2 \
--flavor=woff2
# Unicodeレンジの説明:
# U+0020-007E: 基本ラテン文字(英数字・記号)
# U+3040-309F: ひらがな
# U+30A0-30FF: カタカナ
# U+4E00-9FFF: CJK統合漢字Regular、Bold、Lightなど複数のウェイトを一括でサブセット化するbashスクリプト:
#!/bin/bash
# サブセット化する文字リスト
TEXT_FILE="joyo-kanji.txt"
# 入力フォントディレクトリ
INPUT_DIR="fonts-original"
# 出力ディレクトリ
OUTPUT_DIR="fonts-subset"
# 出力ディレクトリを作成
mkdir -p $OUTPUT_DIR
# すべてのTTFファイルを処理
for font in $INPUT_DIR/*.ttf; do
filename=$(basename "$font" .ttf)
echo "Processing $filename..."
pyftsubset "$font" \
--text-file="$TEXT_FILE" \
--output-file="$OUTPUT_DIR/${filename}.woff2" \
--flavor=woff2 \
--layout-features='*' \
--no-hinting \
--desubroutinize
echo "✓ Created ${filename}.woff2"
done
echo "All fonts processed!"さらにファイルサイズを削減するための高度なオプション:
pyftsubset MyFont.ttf \
--text-file=joyo-kanji.txt \
--output-file=MyFont-optimized.woff2 \
--flavor=woff2 \
--layout-features='*' \
--no-hinting \
--desubroutinize \
--name-IDs='*' \
--drop-tables='DSIG' \
--recalc-bounds \
--recalc-timestamp \
--canonical-order
追加オプションの説明:
--desubroutinize: サブルーチンを展開(互換性向上)--drop-tables: 不要なテーブルを削除--recalc-bounds: バウンディングボックスを再計算--canonical-order: テーブルを標準順序に並べ替え




次は、オンラインツールを使った方法じゃ!コマンドラインに慣れていない方にはこちらの方法が便利じゃ!



オンラインツールでもできるんですね!よろしくお願いします!
URL: https://opentype.jp/subsetfontmk.htm
特徴:
使い方:
FontForgeは、GUIベースのフォント編集ソフトウェアで、サブセット化機能も備えています。
使い方:
Google Fontsを使用する場合、URLパラメータで必要な文字だけをリクエストできます:
<!-- 通常のGoogle Fonts読み込み(全文字) -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
<!-- textパラメータで特定の文字のみ読み込み -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&text=あいうえおかきくけこ&display=swap" rel="stylesheet">この方法は、見出しなど限られた文字しか使わない場合に非常に効果的です。





サブセット化は強力な最適化手法じゃが、いくつかの重要な限界があるのじゃ。ここでは、その理由と対処法を4つ解説するぞ!



サブセット化は便利でも限界があるんですね。
問題点:
これらには、サブセットに含まれない文字が含まれる可能性があります。
対処法:
方法1: ハイブリッドアプローチ
/* 見出し用:限定サブセット */
@font-face {
font-family: 'CustomFont-Heading';
src: url('customfont-heading-subset.woff2') format('woff2');
/* 数百文字のみ、100-300KB */
}
/* 本文用:常用漢字サブセット */
@font-face {
font-family: 'CustomFont-Body';
src: url('customfont-body-joyo.woff2') format('woff2');
/* 常用漢字約2,000文字、2-3MB */
}
/* フォールバック:完全版またはシステムフォント */
h1, h2, h3 {
font-family: 'CustomFont-Heading', 'CustomFont-Body', sans-serif;
}
p, div {
font-family: 'CustomFont-Body', sans-serif;
}方法2: Unicode-rangeディスクリプタの活用
/* ひらがな・カタカナ用サブセット */
@font-face {
font-family: 'CustomFont';
src: url('customfont-kana.woff2') format('woff2');
unicode-range: U+3040-309F, U+30A0-30FF;
}
/* 常用漢字用サブセット */
@font-face {
font-family: 'CustomFont';
src: url('customfont-kanji.woff2') format('woff2');
unicode-range: U+4E00-9FFF;
}
/* 英数字・記号用サブセット */
@font-face {
font-family: 'CustomFont';
src: url('customfont-latin.woff2') format('woff2');
unicode-range: U+0020-007E;
}
body {
font-family: 'CustomFont', sans-serif;
}
ブラウザは必要な文字が含まれるファイルのみをダウンロードするため、効率的です。
問題点:
どれだけサブセット化しても、フォントの構造上、ある程度のファイルサイズは残ります。
対処法:
問題点:
日本語、中国語、韓国語を同時にサポートする必要がある場合、それぞれのサブセットが必要になります。
対処法:
<!-- 言語ごとに異なるフォントを読み込み -->
<html lang="ja">
<head>
<link rel="stylesheet" href="fonts-ja.css">
</head>
</html>
<html lang="zh">
<head>
<link rel="stylesheet" href="fonts-zh.css">
</head>
</html>または、サーバーサイドで言語を判定し、動的に適切なフォントを配信します。
問題点:
コンテンツ更新のたびに使用文字を確認し、サブセットを再生成する必要があります。
対処法:
自動化スクリプトの作成
#!/usr/bin/env node
const fs = require('fs');
const glob = require('glob');
const { exec } = require('child_process');
// すべてのHTMLファイルから使用文字を抽出
const files = glob.sync('src/**/*.html');
let usedChars = new Set();
files.forEach(file => {
const content = fs.readFileSync(file, 'utf-8');
// タグを除去してテキストのみ抽出
const text = content.replace(/<[^>]*>/g, '');
for (let char of text) {
usedChars.add(char);
}
});
// 使用文字をファイルに出力
const charList = Array.from(usedChars).join('');
fs.writeFileSync('used-chars.txt', charList);
// pyftsubsetを実行
exec(`pyftsubset fonts/original.ttf --text-file=used-chars.txt --output-file=fonts/subset.woff2 --flavor=woff2`, (error, stdout, stderr) => {
if (error) {
console.error(`Error: ${error.message}`);
return;
}
console.log('✓ Font subset created successfully!');
});このスクリプトをビルドプロセスに組み込むことで、自動的に最新のサブセットが生成されます。





実はサブセット化以外にも、Webフォントのパフォーマンスを向上させる手法がある。ここでは、その方法を5つ紹介するぞ!



そうなんですね!教えてください!
font-displayは、フォント読み込み中のテキスト表示方法を制御します。
@font-face {
font-family: 'CustomFont';
src: url('customfont.woff2') format('woff2');
font-display: swap; /* 推奨値 */
}font-displayの値:
推奨:font-display: swap – FOITを防ぎ、即座にコンテンツを表示できます。
重要なフォントファイルを事前読み込みすることで、表示を高速化します。
<head>
<!-- 重要なフォントファイルをpreload -->
<link rel="preload"
href="/fonts/customfont.woff2"
as="font"
type="font/woff2"
crossorigin>
<!-- Google Fontsを使う場合はpreconnect -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
</head>注意点:
・preloadは本当に重要なフォント(1-2ファイル)のみに使用
・過度なpreloadはかえってパフォーマンスを悪化させる
・crossorigin属性は必須
可変フォントは、1つのファイルに複数のウェイト(太さ)を含められる新しいフォント技術です。
従来のフォント:
可変フォント:
CSSでの使用例:
@font-face {
font-family: 'CustomVariableFont';
src: url('customfont-variable.woff2') format('woff2-variations');
font-weight: 100 900; /* 100から900まで対応 */
}
h1 {
font-family: 'CustomVariableFont';
font-weight: 800; /* 任意の値を指定可能 */
}
p {
font-family: 'CustomVariableFont';
font-weight: 400;
}
strong {
font-family: 'CustomVariableFont';
font-weight: 650; /* 中間的な太さも指定可能 */
}ユーザーのPCに既にフォントがインストールされている場合、ダウンロードをスキップできます。
@font-face {
font-family: 'CustomFont';
src: local('Custom Font'), /* ローカルを優先 */
local('CustomFont'),
url('customfont.woff2') format('woff2');
}Service Workerを使用してフォントをキャッシュし、2回目以降の訪問を高速化します。
// service-worker.js
const CACHE_NAME = 'font-cache-v1';
const FONT_FILES = [
'/fonts/customfont.woff2',
'/fonts/customfont-bold.woff2'
];
// インストール時にフォントをキャッシュ
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(FONT_FILES))
);
});
// フォントリクエストをキャッシュから返す
self.addEventListener('fetch', event => {
if (event.request.url.includes('/fonts/')) {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
);
}
});




実装するにあたってパフォーマンスの最適化の効果を知るには、定量的に測定することが重要じゃから覚えておくのじゃ!



わかりました!勉強になります!
1. Chrome DevTools
2. WebPageTest
3. Google PageSpeed Insights
実際のWebサイトで最適化を実施した場合の効果:
| 指標 | 最適化前 | 最適化後 | 改善率 |
|---|---|---|---|
| フォントファイルサイズ | 9.2 MB | 450 KB | 95%削減 |
| ページ読み込み時間 | 5.8秒 | 2.1秒 | 64%短縮 |
| LCP(4G回線) | 4.2秒 | 1.8秒 | 57%改善 |
| Lighthouseスコア | 68点 | 94点 | +26点 |
実施した最適化:





Webフォントの実装をうまくやるにはどうしたら良いですか?



うむ。良い質問じゃ。ここでは、 ベストプラクティスの4つの項目を紹介するぞ!
フェーズ1: 基本的な最適化(必須)
font-display: swap を設定フェーズ2: サブセット化(推奨)
フェーズ3: 高度な最適化(大規模サイト向け)
| 用途 | 推奨フォント | 理由 |
|---|---|---|
| 見出し | カスタムフォント(サブセット化) | 限られた文字数、ブランディング重視 |
| 本文 | システムフォント or 軽量Webフォント | 読みやすさとパフォーマンスの両立 |
| UI要素 | システムフォント | 高速表示が最優先 |
| ロゴ | SVG or 画像 | 数文字のみ、デザインの自由度 |
Webフォントが読み込まれない場合に備え、適切なフォールバックを設定:
body {
font-family:
'Custom Web Font', /* カスタムWebフォント */
'-apple-system', /* macOS/iOS San Francisco */
'BlinkMacSystemFont', /* macOS Chrome */
'Segoe UI', /* Windows */
'Hiragino Sans', /* macOS */
'Hiragino Kaku Gothic ProN', /* macOS (旧) */
'Yu Gothic', /* Windows */
'Meiryo', /* Windows (旧) */
'sans-serif'; /* 汎用フォールバック */
}Webフォント実装前の確認項目:



サブセット化や可変フォント、font-displayなど、こんなにたくさんの最適化手法があるんですね!全部組み合わせたらすごく速くなりそう!



その通りじゃ!特に日本語フォントはファイルサイズが大きいから、適切な最適化が必須なんじゃ。まずはサブセット化とfont-display: swapから始めると良いぞい!



早速実践してみます!ありがとうございました!
本記事では、Webフォントのサブセット化と最適化の実践的な手法について、詳しく解説しました。
重要なポイントは以下の通りです。
・日本語フォントの課題:ファイルサイズが5-15MBと巨大で、パフォーマンスに深刻な影響
・サブセット化の効果:pyftsubsetを使用し、必要な文字のみ抽出することで90%以上のサイズ削減が可能
・サブセット化の限界:動的コンテンツへの対応、ファイルサイズの下限、メンテナンスコストに注意が必要
・その他の最適化:font-display: swap、preload/preconnect、WOFF2、可変フォント、Service Workerを組み合わせる
・実装戦略:見出しは限定サブセット、本文は常用漢字サブセット、unicode-rangeで分割配信
・パフォーマンス計測:Chrome DevTools、Lighthouse、WebPageTestで効果を定量的に評価
Webフォントの最適化は、ページ速度とユーザー体験を大幅に改善できる重要な施策です。特に日本語フォントを使用する場合、サブセット化は必須の最適化手法と言えます。
まずは基本的な最適化(WOFF2、font-display: swap)から始め、段階的にサブセット化や可変フォントの採用を進めることをおすすめします。実装後は必ずLighthouseやWebPageTestで効果を測定し、継続的な改善を行いましょう。


本記事でご紹介したWebフォント最適化の技術は、Web制作の実務で非常に重要なスキルです。WithCodeでは、こうした最新技術を含む実践的なWeb制作スキルを学べる環境を提供しています。
副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?
未経験でも心配することはありません。初級コースを受講される方の大多数はプログラミング未経験です。まずは無料カウンセリングで、悩みや不安をお聞かせください!
公式サイト より
今すぐ
無料カウンセリング
を予約!