- 技術 💻
Noto Serif JPの使い方|Noto Sans JPの読み込みと軽量化を実測
結論
Noto Serif JP は、Google Fonts の link を1行入れるか、フォントファイルを自分のサーバーに置いて @font-face で読み込めば Web ページで使えます。日本語フォントは文字数が多く重いため、配信元・使う文字・太さ・font-display の4つを決めてから入れると、表示の遅れや崩れを防げます。
この記事でわかること
- Google Fonts とセルフホスト(Fontsource・自作サブセット)の書き方と、通信量の実測
- pyftsubset で 16.7MB の明朝体を 40KB まで減らした手順と、font-display・太さの違いの実測
- 表示されない・崩れるときの症状→原因→直し方(エラー原文つき)と、PDF・Office での使い方
使い方そのものは数行ですが、「どこから配るか」で通信量が数倍〜数百倍変わるのが日本語フォントの難しいところです。この記事では、手元の Chromium で同じページを何通りもの方法で表示し、届いたバイト数と表示の様子を比べました。
flowchart TD
A[Noto Serif JP を使う] --> B{サーバーに<br>置けるか}
B -- いいえ --> C[Google Fonts<br>の link]
B -- はい --> D{文字は<br>決まっているか}
D -- いいえ --> E[Fontsource<br>で分割配信]
D -- はい --> F[pyftsubset<br>でサブセット]
よく調べられることの答えを先にまとめます。
| やりたいこと | いちばん早い方法 | 詳しい節 |
|---|---|---|
| Noto Serif JP をとにかく表示したい | Google Fonts の CSS2 API の link を head に入れ、font-family を指定 | 最初の5分で表示する |
| Google に接続せず自分のサーバーで配りたい | npm の Fontsource を入れて CSS を読み込む | セルフホストで使う方法 |
| Noto Sans JP が重い・遅いのを直したい | 使う文字だけを pyftsubset でサブセット化し woff2 にする | サブセット化で容量を減らす |
| 読み込み中に文字が消える・ずれる | font-display と line-height を数値で指定する | font-display の違いを実測 |
| 太字が汚い・太さが変わらない | 使う太さを読み込む(可変フォントなら 200〜900 を一度に) | ウェイト(太さ)の指定 |
| 指定したのに Noto Serif JP にならない | family 名の綴り・CORS・ファイルの中身を DevTools で確かめる | 表示されないときの直し方 |
| Word・PowerPoint・PDF で使いたい | PC にインストールし、PDF にはフォントを埋め込んで書き出す | PDF・Office で使う |
| 商用サイトで使ってよいか | OFL なので使える。フォント単体の販売は不可 | ライセンス(OFL) |
確認環境:Ubuntu 24.04.5 LTS・Python 3.13.18。Noto Serif JP と Noto Sans JP の Web 用ファイルは npm の @fontsource-variable/noto-serif-jp・@fontsource-variable/noto-sans-jp 5.3.1(Google Fonts の v34 と同じ分け方の可変フォント、各124ファイル)を作業用のフォルダーに入れ、127.0.0.1 の Python の Web サーバーから配信しました。サブセット化の元には、Ubuntu の fonts-noto-cjk(1:20230817、Noto Serif CJK JP Version 2.002)を使い、fontTools 4.66.1 の pyftsubset(brotli 1.2.1)で変換しました。表示は Playwright 1.63.0 で Chrome for Testing 153.0.8010.12(Chromium)をヘッドレスで起動し、Chrome DevTools Protocol の CSS.getPlatformFontsForNode で「実際に使われたフォント」を記録しています。PDF は Chromium の印刷・LibreOffice 24.2.7.2・ReportLab 5.0.1 で作り、pdffonts 24.02.0 で埋め込みを確かめました。Google Fonts の配信サーバー(fonts.googleapis.com・fonts.gstatic.com)には接続していません。Google Fonts の書き方は Google for Developers の CSS2 API・Getting Started のページ、Windows・Mac へのインストールと Office の埋め込みは Microsoft サポート・Apple サポート、ファイルの種類は notofonts/noto-cjk の README で確かめた範囲だけを書いています。Windows・Mac の実機では動かしていません。図は mermaid で描画を確かめました(確認日 2026年10月29日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Noto Serif JPの使い方|Noto Sans JPの読み込みと軽量化を実測」
Noto Serif JP・Noto Sans JPとは(Noto CJK との関係)
この節では、Noto Serif JP と Noto Sans JP がどんなフォントで、PC に入っている「Noto Serif CJK JP」とどう違うのかが分かります。
Noto Serif JP は日本語の明朝体、Noto Sans JP は日本語のゴシック体です。どちらも Google と Adobe が共同で開発した Noto CJK(中国語・日本語・韓国語)フォントの日本語版で、Adobe 側では「源ノ明朝」「源ノ角ゴシック」という名前で配られている書体と同じデザインです。
名前が似たフォントがいくつもあり、ここで迷う人が多いので整理します。notofonts/noto-cjk の README では、配布の形が次のように分かれています。
| 名前 | 中身 | 手元で確かめたこと |
|---|---|---|
| Noto Serif CJK JP | 日・中・韓の字形をすべて持つ「言語別 OTF」または5言語入りの OTC の日本語の顔 | Ubuntu の fonts-noto-cjk に入っていた。1ウェイトで 65,535 グリフ、文字 44,777 個 |
| Noto Serif JP | 日本で使う字形だけに絞った「地域別サブセット OTF」。README は迷ったらこれを勧めている | Google Fonts と同じ分け方の Fontsource 版で、文字 16,652 個 |
| Noto Serif JP(可変フォント) | 太さを 200〜900 の間で自由に変えられる1つのフォント | wght 軸 200〜900、名前付きの太さは ExtraLight〜Black の8つ |
| Noto Sans JP(可変フォント) | ゴシック体。太さは 100〜900 | wght 軸 100〜900、Thin〜Black の9つ。文字 16,657 個 |
fontTools で中身を読むと、名前と版は次のとおりでした。
Noto Serif CJK JP(fonts-noto-cjk) Version 2.002 glyphs 65535 cmap 44777
Noto Serif JP(Fontsource v34) Version 2.003-H1 wght 200..900 cmap 16652 輪郭 glyf
Noto Sans JP(Fontsource v34) Version 2.004-H2 wght 100..900 cmap 16657 輪郭 glyf
大事なのは、CSS で font-family: "Noto Serif JP" と書いても、PC に入っている「Noto Serif CJK JP」は使われないことです。手元の Linux で fc-match に聞くと、Noto Serif JP という名前のフォントは見つからず、別のフォント(Inter)が返りました。
$ fc-match "Noto Serif JP"
Inter-Regular.otf: "Inter" "Regular"
$ fc-match "Noto Serif CJK JP"
NotoSerifCJK-Regular.ttc: "Noto Serif CJK JP" "Regular"
Web フォントを読み込まずに font-family: "Noto Serif JP", serif; と書いたページを Chromium で開くと、使われたのは serif の代わりの Noto Serif CJK JP でした。たまたまこの PC に似たフォントがあっただけで、ほかの PC では別の明朝体になります。どの PC でも同じ見た目にしたいなら、Web フォントとして読み込む必要があります。
Noto Serif JPの使い方:最初の5分でWebページに表示する
この節では、いちばん短い手順で Noto Serif JP を Web ページに表示する方法と、その結果の確かめ方が分かります。
いちばん早いのは、Google Fonts の CSS を link で読み込む方法です。Google for Developers の CSS2 API のページに書かれた書式に合わせると、Noto Serif JP の全ウェイト(200〜900)は次の1行になります。
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Serif+JP:wght@200..900&display=swap">
<style>
h1, h2 { font-family: "Noto Serif JP", serif; font-weight: 700; }
</style>
link を head に入れる
ファミリー名の空白は「+」にする。太さは wght@400;700 のように「;」区切りの昇順、範囲なら wght@200..900 と書く。
font-family を指定する
名前は "Noto Serif JP"(ゴシック体は "Noto Sans JP")。最後に serif・sans-serif の総称名を添えておく。
display=swap を付ける
読み込み中も別のフォントで文字を見せる。付けないと既定の auto になり、応答を1.5秒遅らせた実験では、届くまで文字が消えた。
DevTools で確かめる
要素を選び、「Computed」タブの最下部「Rendered Fonts」に Noto Serif JP と出れば読み込めている。
手順4が大切です。font-family に書いた名前は「希望」で、実際に描かれたフォントは別です。手元では CDP の CSS.getPlatformFontsForNode で同じ情報を取り、Web フォントなら isCustomFont: true、PC のフォントなら false になるのを確かめました。
ゴシック体の Noto Sans JP も、名前を変えるだけで同じ書き方です。日本語の font-family の並べ方(游ゴシック・ヒラギノとの組み合わせ)は、関連記事「CSS font-family日本語おすすめ指定|游ゴシック対応コピペ集」で扱っています。この記事では Noto の2書体に絞り、読み込みと軽量化を深掘りします。
Google Fontsで読み込む方法(CSS2 APIの書き方)
この節では、Google Fonts の URL の書き方(太さ・複数ファミリー・text パラメーター)と、使う前に知っておく点が分かります。
CSS2 API の基本は https://fonts.googleapis.com/css2?family=名前:軸@値&display=値 です。公式ページの記述から、Noto の2書体でよく使う形をまとめます。
| やりたいこと | family の書き方 | 注意 |
|---|---|---|
| 明朝体を 400 と 700 だけ | Noto+Serif+JP:wght@400;700 |
値は小さい順に「;」でつなぐ |
| 明朝体の全ウェイト | Noto+Serif+JP:wght@200..900 |
範囲は「..」。重なる範囲は書けない |
| 明朝体とゴシック体の両方 | family=Noto+Serif+JP:wght@700&family=Noto+Sans+JP:wght@400;700 |
family= をファミリーごとに書く |
| ロゴなど決まった文字だけ | Noto+Serif+JP&text=%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE |
text= は URL エンコードし、1リクエストに1回 |
| 読み込み中の表示 | &display=swap |
auto・block・swap・fallback・optional から選ぶ |
Zenn などで「Noto Sans Japanese と書いたら読み込めなかった」という報告があるとおり、Google Fonts の画面の表示名(Noto Serif Japanese)と、URL・CSS で使う名前(Noto Serif JP)は違います。URL は Noto+Serif+JP、CSS は "Noto Serif JP" です。Nuxt の @nuxtjs/google-fonts のように設定ファイルで名前を書くモジュールでも、同じ形です。
読み込みを早めるために、配信元へ先に接続しておく preconnect を head の先頭に書く例も広く使われています(Google の CSS2 API・Getting Started のページには記述が無く、HTML の一般的な仕組みです)。フォントは CORS のモードで取得される(後の節で CORS エラーを実際に出しています)ため、フォントの配信元への preconnect には crossorigin を付けます。
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap">
Google Fonts の link が向く
サーバーにファイルを置けない(ノーコードのサイト等)
表示する文字が毎回変わる(ブログ・CMS)
まず見た目を試したい
セルフホストが向く
外部へのリクエストを増やしたくない(社内規程・同意の管理)
キャッシュや配信をすべて自分で決めたい
表示する文字が決まっていてサブセット化できる
セルフホストで使う方法(Fontsource・自分のサーバー)
この節では、Google Fonts に接続せずに、自分のサーバーから Noto Serif JP・Noto Sans JP を配る2つの方法と、手元での配信結果が分かります。
方法1:npm の Fontsource を使う
Fontsource は、Google Fonts と同じファイルを npm のパッケージとして配っているプロジェクトです。手元では可変フォント版を入れました。
$ npm i @fontsource-variable/noto-serif-jp@5.3.1 @fontsource-variable/noto-sans-jp
added 2 packages in 975ms
$ ls node_modules/@fontsource-variable/noto-serif-jp/files | wc -l
124
$ du -cb node_modules/@fontsource-variable/noto-serif-jp/files/*.woff2 | tail -1
7468952 total
Vite・webpack などのバンドラーを使うなら、JavaScript か CSS で読み込むだけです。CSS 側のファミリー名は "Noto Serif JP Variable"(可変フォント版)になる点に注意します。
// main.js
import '@fontsource-variable/noto-serif-jp';
import '@fontsource-variable/noto-sans-jp';
body { font-family: "Noto Sans JP Variable", sans-serif; }
h1, h2 { font-family: "Noto Serif JP Variable", serif; font-weight: 700; }
パッケージの index.css の中身は、124個の @font-face です。1つ目は次の形で、unicode-range に書かれた文字がページに出たときだけ、そのファイルが読み込まれます。
/* noto-serif-jp-[0]-wght-normal */
@font-face {
font-family: 'Noto Serif JP Variable';
font-style: normal;
font-display: swap;
font-weight: 200 900;
src: url(./files/noto-serif-jp-0-wght-normal.woff2) format('woff2-variations');
unicode-range: U+25ee8,U+25f23,U+25f5c, ...(以下略)
}
方法2:ファイルを置いて @font-face を自分で書く
バンドラーを使わないサイト(WordPress のテーマなど)では、woff2 をサーバーに置き、@font-face を書きます。自分でサブセット化した1ファイルを使う場合の最小形です。
@font-face {
font-family: "Noto Serif JP";
src: url("/fonts/noto-serif-jp-400-sub.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Noto Serif JP";
src: url("/fonts/noto-serif-jp-700-sub.woff2") format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
}
WordPress なら、この CSS を functions.php から wp_enqueue_style() で1回だけ読み込み、テーマとプラグインで二重に読み込んでいないかを DevTools の Network タブ(Font)で確かめます。
セルフホストでは、サーバーの応答ヘッダーも自分で決めます。
- 1別ドメインから配るなら Access-Control-Allow-Origin を付ける付けないと Chromium はフォントを捨てる(エラー原文は後の節)
- 2ファイル名に版やハッシュを入れて長くキャッシュするCache-Control: max-age=31536000, immutable など。差し替えはファイル名を変える
- 3Content-Type は font/woff2間違った種類や HTML のエラーページが返ると、デコードに失敗する
- 4ライセンスのファイルを一緒に置くOFL は再配布時に著作権表示とライセンス文を添える条件がある
キャッシュの指定の考え方は、関連記事「Cache-Controlのno-cacheとno-storeの違いと正しい設定」で扱っています。Next.js の場合は、next/font/google がビルド時にフォントを取り込んで同じドメインから配る仕組みを公式ドキュメントで説明しています(ブラウザから Google へのリクエストは出ない)。Next.js の基本は関連記事「Next.js App Router 入門|v16対応・実際のビルド結果つき」で扱っています。
日本語フォントは何が重いのか:unicode-rangeの分割を実測
この節では、Noto Serif JP がなぜ「重い」と言われるのかと、分割配信で実際に何ファイル・何バイト届くのかが分かります。
英語のフォントは数百文字で済みますが、日本語はかな・漢字・記号で1万6千字を超えます。Noto Serif JP を丸ごと1ファイルにすると数 MB〜十数 MB になるため、Google Fonts は文字を約120のグループに分け、ページに出てくる文字を含むグループだけを読み込ませるしくみ(unicode-range)を使っています。Fontsource も同じ分け方です。
同じ Fontsource の CSS を読み込んだページを2つ作り、Chromium で開いて届いた woff2 を数えました。
| ページ | 使った文字の種類 | 届いた woff2 | 合計バイト | fonts.ready まで |
|---|---|---|---|---|
| 短いページ(見出しとメニュー、5行) | 134種類 | 8ファイル | 283,808 | 216ms |
| 長い記事(約1万5千字) | 594種類 | 41ファイル | 1,182,516 | 643ms |
| 参考:全124ファイル(明朝体) | 16,652種類 | 124ファイル | 7,468,952 | ― |
| 参考:全124ファイル(ゴシック体) | 16,657種類 | 124ファイル | 5,473,652 | ― |
時間は 127.0.0.1 からの配信なので回線の遅れは入っていません。全ファイルの合計では、明朝体はゴシック体より約1.4倍重いことも分かります。
Google Fonts 版に入っていない文字
長い記事では、Noto Serif JP のほかに Noto Serif CJK JP が3文字分だけ混ざっていました。ローマ数字の「Ⅱ」がどのファイルにも無かったためです。JIS 第1・第2水準で調べると、次の49文字がありませんでした。
serif 49 ≒ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω
sans 49 ≒ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω
ギリシャ文字と「≒」「Ⅱ」は、ページでは次の候補のフォント(この PC では Noto Serif CJK JP や WenQuanYi Zen Hei)で描かれました。数式や単位で α・β・Ω を使うページでは、その文字だけ書体が変わることがあるので、気になる場合は自分でサブセットを作るときに含めます。
サブセット化で容量を減らす(pyftsubsetの実測)
この節では、pyftsubset で Noto Serif JP を必要な文字だけに減らす手順と、文字の範囲ごとの容量・時間の実測が分かります。
サブセット化は、フォントから使わない文字を取り除くことです。文字が決まっている見出し・ロゴ・LP では、分割配信より小さくできます。
python3 -m venv .venv
.venv/bin/pip install fonttools brotli
.venv/bin/pyftsubset NotoSerifCJK-Regular.ttc --font-number=0 \
--text-file=page.txt \
--flavor=woff2 \
--output-file=noto-serif-jp-400-sub.woff2
手元の Noto はコレクション(.ttc)なので、日本語の顔を --font-number=0 で選んでいます(1以降は KR・SC・TC・HK)。Google Fonts の配布ページからダウンロードした .ttf を使う場合、この指定は要りません。
文字の範囲を変えて、容量と変換時間を測りました。変換時間は 2 CPU を他の作業と分け合う環境での値です。
| 残した文字 | 文字数 | woff2 の大きさ | 変換時間 |
|---|---|---|---|
| 丸ごと(日本語の顔の全グリフ) | 44,777 | 16,672,424 | 355秒 |
| JIS 第1・第2水準+記号+英数 | 6,355字+619 | 4,192,120 | 72秒 |
| JIS 第1水準+記号+英数 | 2,965字+619 | 1,782,492 | 18秒 |
| 長い記事で使った文字だけ | 594 | 255,784 | 2.8秒 |
| 短いページで使った文字だけ | 134 | 40,048 | 0.9秒 |
同じ短いページなら、分割配信の 283,808 バイトに対して、サブセット1ファイルは 40,048 バイト(約7分の1)でした。長い記事でも 1,182,516 バイトが 255,784 バイトになりました。Chromium で開いた時間(fonts.ready まで)は、サブセット1ファイルが 83ms、丸ごとの 16.7MB は 127.0.0.1 からでも 1,053ms かかりました。
--layout-features は「*」にするか
上位の記事では --layout-features='*' を付けて OpenType の機能をすべて残す方法が紹介されています。既定のままとの違いを、残った機能の一覧で比べました。
jis1-def.woff2(既定) 6962 glyphs 1,782,492 bytes
GSUB ['ccmp', 'liga', 'locl', 'vert', 'vrt2']
GPOS ['halt', 'kern', 'palt', 'vhal', 'vkrn', 'vpal']
jis1.woff2(--layout-features=*) 7774 glyphs 1,977,624 bytes
GSUB ['aalt', 'ccmp', 'dlig', 'fwid', 'hwid', 'jp78', 'jp83', 'jp90', 'liga', 'locl', 'nlck', 'pwid', 'vert', 'vrt2']
GPOS ['halt', 'kern', 'palt', 'vhal', 'vkrn', 'vpal']
fontTools のドキュメントに載っている既定の一覧(calt・ccmp・kern・liga・locl など)には vert・palt の名前がありませんが、手元の 4.66.1 では既定のままでも、縦書き(vert・vrt2)、カーニング(kern)、文字詰め(palt)は残りました。「*」で増えたのは、JIS78・JIS83 の字形(jp78・jp83)、全角・半角・プロポーショナルの切り替え(fwid・hwid・pwid)などで、容量は約11%増えました。CSS の font-variant-east-asian で jis78 や full-width を使わないなら、既定で困らないというのが手元の結論です。ただし、別の版の fontTools や GUI のサブセットツールでは残る機能が違うので、作ったファイルを上のように一覧で確かめると安心です。
palt(文字詰め)が効くことも確かめました。20px の「「お問い合わせ」は、こちらへ。」の幅は、通常 300.00px、font-feature-settings: "palt" で 250.91px になり、約16%詰まりました。
サブセット化の範囲
見分ける問い:「この場所に出る文字は、公開後に増えるか」
font-displayの違いをChromiumで実測(swap・block・optional)
この節では、font-display の5つの値で、読み込み中に文字がどう見えるか、レイアウトがどれだけずれるかが分かります。
MDN は font-display の各値を「短い」「非常に短い」といった言葉で説明していて、具体的な秒数は実装に任されています。そこで、フォントの応答を 1.5 秒遅らせるサーバーを 127.0.0.1 に立て、読み込み中のページを時間ごとに撮影しました。代わりのフォントには、違いが見えるように IPA P ゴシックを指定しています。
| font-display | 約0.4秒 | 約1秒 | 約2秒(読み込み後) | CLS |
|---|---|---|---|---|
| auto(既定) | 文字が見えない | 文字が見えない | Noto Serif JP | 0 |
| block | 文字が見えない | 文字が見えない | Noto Serif JP | 0 |
| swap | ゴシックで表示 | ゴシックで表示 | Noto Serif JP に切り替わる | 0.0222 |
| fallback | ゴシックで表示 | ゴシックで表示 | Noto Serif JP に切り替わる | 0.0222 |
| optional | ゴシックで表示 | ゴシックで表示 | ゴシックのまま(切り替えない) | 0 |
「文字が見えない」は、撮影した画像の黒い画素が0個だったことを指します(表示後は 8,698 個)。auto と block では、フォントが届くまでの 1.5 秒間、文章が丸ごと消えていました。swap と fallback は最初から文字が読め、届いた時点で明朝体に切り替わり、そのときにレイアウトのずれ(CLS 0.0222)が出ました。optional は、最初の短い時間に間に合わなかったので、届いた後もゴシックのままでした(次に開いたときはキャッシュから明朝体で表示されます)。
ずれの原因は line-height: normal
切り替わりでずれる理由を、16px の文字で行の高さを測って確かめました。
line-height: normal の行の高さ(16px)
Noto Serif JP 23.00px
Noto Sans JP 24.00px
IPA P ゴシック 16.00px
DejaVu Serif 19.00px
Noto Serif JP(line-height: 1)16.00px
Noto の2書体は、フォントの中の行の高さの設定(ascent 1151・descent 286、1000 単位)が大きく、line-height を指定しないと1.4倍以上の高さになります。代わりのフォントとの差がそのままずれになるので、本文に line-height: 1.8 のような数値を指定しておくと、切り替わっても行の高さが変わりません。ボタンの文字が上下中央からずれて見えるときも、同じ設定が原因です。
1本文は swap
文字が消えないことを優先する。line-height を数値で指定して、切り替わりのずれを小さくする。
2ずれを0にしたいなら optional
初回は代わりのフォントのまま。2回目以降に Noto で表示される。
3ロゴは block も選択肢
別の書体で一瞬見えるのを避けたい短い文字だけ。本文には使わない。
見出しの文字の大きさを画面幅に合わせて変える方法は、関連記事「CSS clamp()の使い方|フォントサイズ計算式・早見表とSass関数」で扱っています。
Noto Serif JPのウェイト(太さ)の指定と可変フォント・疑似ボールド
この節では、Noto Serif JP の太さを指定するときに「読み込んでいない太さ」を使うと何が起きるかと、可変フォントの扱いが分かります。
同じ文字列を 40px で、次の6通りに表示し、文字の黒い画素の数を数えました。
| 読み込んだフォント | font-weight | 黒い画素 | 見た目 |
|---|---|---|---|
| 可変フォント(200〜900) | 400 | 2,673 | 通常の明朝体 |
| 可変フォント(200〜900) | 700 | 4,322 | 本物の太字。横線は細いまま |
| 可変フォント(200〜900) | 900 | 5,062 | いちばん太い |
| 400 だけのサブセット | 400 | 2,688 | 通常の明朝体 |
| 400 だけのサブセット | 700 | 4,514 | 疑似ボールド。横線まで一様に太る |
| 400 だけ+font-synthesis: none | 700 | 2,688 | 太くならない |
400 しか読み込んでいないのに 700 を指定すると、ブラウザーが輪郭を機械的に太らせる「疑似ボールド」になりました。明朝体の特徴である横線の細さが失われ、黒い画素は本物の 700 より多い 4,514 個でした。太字を使うなら、その太さのファイルを読み込むのが基本です。font-synthesis: none を付けると疑似ボールドを止められますが、太くならないだけなので、読み込み漏れに気づくための確認に向きます。
可変フォントは 200〜900 のどの太さも本物で描けます。Google Fonts なら wght@200..900、Fontsource なら @fontsource-variable を使います。
「ExtraLight」と表示されても太さは正しい
可変フォントを使うと、DevTools の Rendered Fonts や PDF のフォント名に「Noto Serif JP ExtraLight」と出ます。これは可変フォントの中の名前が既定値(wght 200)のものだからで、実際の太さは CSS の font-weight で決まります。上の表でも、名前は ExtraLight のまま、400 の黒い画素は静的な 400(2,688)とほぼ同じ 2,673 でした。
- 1太さを1つだけ使う → 静的な 400 か 700 を1つ見出しだけ明朝体 700、など
- 2太さを2つ使う → 静的な2つか可変フォント文字が決まっているなら静的2つをサブセット化
- 3太さを3つ以上使う → 可変フォントwght@200..900 で1回の読み込み
- 4太さのアニメーション → 可変フォントのみfont-weight を transition で変えられる
local()とインストール済みのNoto Serif JPを使う(OS別)
この節では、PC に入っているフォントを先に使わせる local() の書き方と、OS ごとの名前の違いが分かります。
@font-face の src に local() を先に書くと、PC にそのフォントがあればダウンロードせずに使えます。手元の Linux で、local() に入れる名前を5通り試しました。
| local() の名前 | 結果 | 理由 |
|---|---|---|
local("Noto Serif JP") |
error(使われない) | この PC に同名のフォントが無い |
local("NotoSerifJP-Regular") |
error(使われない) | 同上 |
local("Noto Serif CJK JP") |
loaded | フルネーム(name ID 4)と一致 |
local("NotoSerifCJKjp-Regular") |
loaded | PostScript 名(name ID 6)と一致 |
local("Noto Serif CJK JP Regular") |
error(使われない) | 実際のフルネームに Regular は付いていない |
local() は、ファミリー名ではなくフルネームか PostScript 名と一致したときだけ使われます。名前はフォントによって違うため、手元では fontTools で name テーブルを読んで確かめました。local() が当たったページでは、woff2 のリクエストは0件、fonts.ready まで 72ms でした。
@font-face {
font-family: "NSJ";
src: local("Noto Serif JP"), local("NotoSerifJP-Regular"),
local("Noto Serif CJK JP"), local("NotoSerifCJKjp-Regular"),
url("/fonts/noto-serif-jp-400-sub.woff2") format("woff2");
font-display: swap;
}
ただし PC のフォントは版がばらばらです。見た目を厳密にそろえたいなら local() を書かず url() だけにするほうが確実です。
PC へのインストール(Word・デザインツール用)
- Windows:Microsoft サポートの「フォントを追加する」の手順では、ダウンロードした zip を右クリックして「抽出」、フォントを右クリックして「インストール」を選びます。C:\Windows\Fonts へのドラッグでも入ります。
- Mac:Apple サポートの「MacのFont Bookでフォントをインストールして検証する」では、Finder でフォントファイルをダブルクリックし、表示されたダイアログでインストールを確定します。Font Book のウインドウへのドラッグでも入ります。
- Linux:fontconfig が読むフォルダー(利用者ごとなら ~/.local/share/fonts)に置き、fc-cache を実行します。
PC に入れるのは .ttf・.otf です。Fontsource や Google Fonts の Web 用の woff2 は文字が約120個のファイルに分かれていて、手元で fc-scan に読ませると、どのファイルも名前が「Noto Serif JP ExtraLight」の一部分として扱われました。Web 用の分割ファイルは PC へのインストールには使わないのが無難です。
Noto Serif JPが表示されない・崩れるときの直し方(症状→原因→直し方)
この節では、Noto Serif JP・Noto Sans JP が表示されない、別の書体になる、崩れるときの原因を、手元で再現したエラー原文と一緒に確かめられます。
| 症状 | 原因 | 直し方 |
|---|---|---|
| 指定したのに別の書体になる(エラーは出ない) | @font-face の名前と font-family の名前が違う(Fontsource 可変版は "Noto Serif JP Variable") | CSS の名前を合わせる。Rendered Fonts で確かめる |
| Console に CORS のエラー | 別ドメインのフォントに Access-Control-Allow-Origin が無い | 配信側にヘッダーを付けるか、同じドメインから配る |
| Failed to decode downloaded font | woff2 の URL に HTML(エラーページ等)が返っている | URL を直接開いて中身を確かめる。パスを直す |
| 404 で読み込めない | CSS からの相対パスがずれている | CSS ファイルの場所を基準に url() を書き直す |
| 一部の文字だけ書体が違う | その文字がフォント(サブセット)に入っていない | サブセットに文字を足す。ギリシャ文字は Google Fonts 版にも無い |
| 太字の横線まで太い・にじむ | 700 を読み込まずに疑似ボールドになっている | 700 のファイルか可変フォントを読み込む |
| 読み込み中に文字が消える | font-display が auto・block | display=swap か font-display: swap |
| 切り替わりでガタッとずれる・ボタンの文字が下がる | line-height: normal で行の高さが変わる | line-height を数値で指定する |
Chromium の Console に出た原文です。CORS のエラーは、ページを 127.0.0.1:19001、フォントを Access-Control-Allow-Origin を付けない 127.0.0.1:19003 から配って出しました。
Access to font at 'http://127.0.0.1:19003/fonts/page.woff2' from origin 'http://127.0.0.1:19001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Failed to load resource: net::ERR_FAILED
woff2 の URL に HTML のエラーページを置いたときは、次の2行が出ました。1008821359 は16進数で 0x3C21646F、文字にすると「<!do」(<!doctype の先頭)で、フォントではなく HTML が返っていることがこの数字から分かります。
Failed to decode downloaded font: http://127.0.0.1:19001/fonts/fake.woff2
OTS parsing error: invalid sfntVersion: 1008821359
ファイルが無いときは Failed to load resource: the server responded with a status of 404 (File not found) でした。どの場合も、読み込みに失敗すると次の候補のフォントで黙って表示されるので、見た目だけでは気づきにくい点に注意します。CORS のエラー全般の読み方は、関連記事「CORSエラーの原因と解決方法|エラーメッセージ別に解説」で扱っています。
サブセット化のときのエラー
$ pyftsubset NotoSerifCJK-Regular.ttc --text-file=t.txt --output-file=x.ttf
fontTools.ttLib.TTLibFileIsCollectionError: specify a font number between 0 and 4 (inclusive)
$ pyftsubset NotoSerifCJK-Regular.ttc --font-number=0 --text-file=t.txt --flavor=woff2 --output-file=x.woff2
ImportError: No module named brotli
1つ目は .ttc に --font-number を付け忘れたとき、2つ目は woff2 の圧縮に使う brotli が入っていないときです。pip install brotli で直りました。
PDF・Word・PowerPointでNoto Serif JPを使う
この節では、Noto Serif JP を使った文書を PDF にしたときにフォントが埋め込まれるかと、Office で別の PC に渡すときの注意が分かります。
Web ページを PDF にする(Chromium の印刷)
可変フォントの Noto Serif JP で表示したページを Chromium で PDF にし、pdffonts で中身を見ました。
name type encoding emb sub uni
------------------------------------ ----------------- ---------------- --- --- ---
AAAAAA+NotoSerifJP-ExtraLight Type 3 Custom yes yes yes
BAAAAA+NotoSerifJP-ExtraLight Type 3 Custom yes yes yes
...(同じ名前が全部で15行)
PAAAAA+NotoSerifCJKjp-Regular Type 3 Custom yes yes yes
emb(埋め込み)・sub(サブセット)がどちらも yes で、使った文字だけが埋め込まれていました。可変フォントは Type 3 で入り、名前は ExtraLight と出ます。最後の行は静的なサブセット(中身は Noto Serif CJK JP)で描いた行の分です。
Word で指定したフォントが PC に無いとき
python-docx で、フォントを「Noto Serif JP」と「Noto Serif CJK JP」に指定した2つの .docx を作り、Noto Serif JP の入っていない環境の LibreOffice で PDF にしました。
== Noto Serif JP を指定した docx
BAAAAA+Inter-Regular Type 1 Builtin yes yes yes
CAAAAA+WenQuanYiZenHei TrueType WinAnsi yes yes yes
== Noto Serif CJK JP を指定した docx
BAAAAA+NotoSerifCJKjp-Regular Type 1 Builtin yes yes yes
フォントが無い PC では、明朝体の指定が黙ってゴシック体(WenQuanYi Zen Hei)に置き換わりました。エラーは出ません。Word・PowerPoint の文書を渡すときは、相手の PC にもフォントを入れてもらうか、文書にフォントを埋め込みます。Microsoft サポートの「Benefits of embedding custom fonts」では、Windows の Word・PowerPoint で[ファイル]→[オプション]→[保存]の「ファイルにフォントを埋め込む」にチェックを入れる手順が説明されています(「使用されている文字だけを埋め込む」を選ぶと小さくなる代わりに編集が制限されます)。埋め込めるかどうかはフォントの OS/2 テーブルの fsType で決まり、手元の Noto Serif CJK JP・Noto Serif JP・Noto Sans JP はどれも 0(制限なし)でした。
Python(ReportLab)で PDF を作る
reportlab.pdfbase.ttfonts.TTFError: TTC file "/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc": postscript outlines are not supported
ReportLab の TTFont は TrueType の輪郭(glyf)だけに対応していて、CFF の輪郭を持つ Noto Serif CJK JP(.ttc・.otf)は読み込めませんでした。Google Fonts 版の Noto Serif JP は glyf の輪郭なので、fontTools の instancer で太さを 400 に固定した .ttf にすると登録でき、pdffonts で AAAAAA+NotoSerifJP-ExtraLight TrueType ... yes yes yes と埋め込まれたことを確かめました。
Noto Serif JPのライセンス(OFL):商用利用・改変・埋め込み
この節では、Noto Serif JP・Noto Sans JP を商用サイトや配布物で使うときに、OFL で何が許され、何に気をつけるかが分かります。
Fontsource のパッケージに入っている LICENSE と、fonts-noto-cjk の著作権表示を読みました。どちらも SIL Open Font License 1.1 です。ライセンス本文の「PERMISSION & CONDITIONS」を要約します(法的な助言ではありません)。
| やりたいこと | OFL での扱い |
|---|---|
| 商用の Web サイト・アプリで表示する | 使える(use・embed が許されている) |
| サブセット化・woff2 に変換して配る | 改変版として配れる。OFL のまま配り、著作権表示とライセンス文を添える |
| PDF・印刷物・ロゴ画像に使う | 使える。作った文書には OFL は及ばない(条件5) |
| アプリやテーマに同梱して販売する | できる(条件2)。フォント単体での販売は不可(条件1) |
| 改変版に元と同じ名前を付ける | Reserved Font Name があると不可(条件3) |
手元のフォントの著作権表示(name ID 0)は「© 2017-2023 Adobe」で、Reserved Font Name の指定は見当たりませんでした。サブセット化したファイルを配るときは、LICENSE(OFL.txt)を同じ場所に置いておくと条件2を満たしやすくなります。Fontsource の metadata.json にも "license": {"type": "OFL-1.1"} と書かれていました。
Noto Serif JPとNoto Sans JPの使い分け判断表
この節では、明朝体とゴシック体をどこに使い分け、どの読み込み方を選ぶかを、目的別に判断できます。
| 場面 | 書体と太さ | 読み込み方 |
|---|---|---|
| コーポレートサイトの見出し | Noto Serif JP 600〜700 | 見出しの文字だけサブセット化(数十 KB) |
| ブログ・ニュースの本文 | Noto Sans JP 400、強調 700 | Google Fonts か Fontsource の分割配信 |
| 小説・エッセイなど長い読み物 | Noto Serif JP 400、line-height 1.8〜2 | 分割配信。縦書きなら vert が残っているか確かめる |
| 管理画面・表・ボタン | Noto Sans JP 400〜500 | PC のフォントで済ませる選択肢もある |
| LP・キャンペーンページ | 見出し Noto Serif JP、本文 Noto Sans JP | 見出しはサブセット、本文は分割配信 |
| 社内の Word・PowerPoint | どちらも可 | 全員の PC にインストールするか、文書に埋め込む |
よくある質問
この節では、Noto Serif JP・Noto Sans JP の使い方でよく聞かれる質問への答えが分かります。
Q. Noto Serif JP は無料で商用利用できますか?
はい。SIL Open Font License 1.1 で、商用の Web サイト・アプリ・印刷物に使えます。フォントだけを単体で販売することはできません。
Q. Noto Serif JP と源ノ明朝は同じですか?
Google と Adobe が共同で開発した同じデザインの書体で、配布元と名前が違います。CSS の font-family では別の名前として扱われます。
Q. Noto Serif JP と Noto Serif CJK JP の違いは?
Noto Serif CJK JP は中国語・韓国語の字形も持つ全言語版、Noto Serif JP は日本で使う字形に絞った版です。手元では、文字の数が 44,777 個と 16,652 個でした。
Q. Google Fonts で読み込むとき、ファミリー名は何と書きますか?
URL では Noto+Serif+JP、CSS では "Noto Serif JP" です。画面に出る「Noto Serif Japanese」では読み込めません。
Q. font-display は何を指定すればよいですか?
本文は swap が無難です。手元では auto・block だと読み込みまで文字が消えました。ずれを出したくないなら optional を選び、どちらの場合も line-height を数値で指定します。
Q. ダウンロードしたフォントを自分のサーバーに置いてよいですか?
OFL では再配布が許されています。著作権表示とライセンス文を一緒に置きます。
Q. サブセット化すると縦書きや文字詰めが効かなくなりますか?
fontTools 4.66.1 の既定では vert・vrt2・palt・kern が残りました。作ったファイルの機能の一覧を fontTools で確かめると確実です。
Q. ギリシャ文字だけ書体が変わります。
Google Fonts と同じ分け方の Fontsource 版には、α・Ω などのギリシャ文字と「≒」「Ⅱ」が入っていませんでした。その文字は次の候補のフォントで描かれます。
まとめ
この節では、Noto Serif JP・Noto Sans JP を使うときの要点を5つで振り返れます。
- 使い方は2通り。Google Fonts の link(
family=Noto+Serif+JP:wght@200..900&display=swap)か、Fontsource・自作の woff2 をセルフホストする。 - 名前に注意。CSS は "Noto Serif JP"、Fontsource 可変版は "Noto Serif JP Variable"。PC の Noto Serif CJK JP とは名前が違い、local() はフルネームか PostScript 名で書く。
- 文字が決まっている場所はサブセット化。短いページでは分割配信 283,808 バイトが、pyftsubset の1ファイルで 40,048 バイトになった。
- 本文は swap と line-height の数値指定。auto・block では 1.5 秒の遅れの間、文字が消えた。切り替わりのずれは line-height: normal が原因。
- 太さと文書の埋め込みを確かめる。読み込んでいない太さは疑似ボールドになり、フォントの無い PC の Word では明朝体がゴシック体に置き換わった。
参考・出典
確認日はいずれも 2026年10月29日です。
- Google for Developers「CSS API update(CSS2 API)」:https://developers.google.com/fonts/docs/css2
- Google for Developers「Get Started with the Google Fonts API」:https://developers.google.com/fonts/docs/getting_started
- Google for Developers「Technical Considerations」:https://developers.google.com/fonts/docs/technical_considerations
- notofonts/noto-cjk「Serif/README.md」:https://github.com/notofonts/noto-cjk/blob/main/Serif/README.md
- Fontsource「@fontsource-variable/noto-serif-jp」5.3.1(npm パッケージの LICENSE・metadata.json・index.css)
- SIL「SIL Open Font License 1.1」(パッケージの LICENSE に記載の URL):http://scripts.sil.org/OFL
- MDN「font-display」:https://developer.mozilla.org/ja/docs/Web/CSS/@font-face/font-display
- MDN「rel=preconnect」:https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Attributes/rel/preconnect
- Next.js Docs「Font Optimization」:https://nextjs.org/docs/app/getting-started/fonts
- Microsoft サポート「フォントを追加する」:https://support.microsoft.com/ja-jp/office/フォントを追加する-b7c5f17c-4426-4b53-967f-455339c564c1
- Microsoft サポート「Benefits of embedding custom fonts」:https://support.microsoft.com/en-us/office/fonts/benefits-of-embedding-custom-fonts
- Apple サポート「MacのFont Bookでフォントをインストールして検証する」:https://support.apple.com/ja-jp/guide/font-book/fntbk1000/mac
- fontTools「fontTools.subset(pyftsubset)」:https://fonttools.readthedocs.io/en/latest/subset/index.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Noto Serif JPの使い方|Noto Sans JPの読み込みと軽量化を実測」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。