Noto Sans Webフォントガイド
問題
Noto Sans(特に日本語コンテンツ向けのNoto Sans JP)を読み込む際、AIエージェントはいくつかの典型的なミスを犯しがちです。実際には2〜3ウェイトしか使わないのに9ウェイトすべてを読み込む、font-display: swapを省略する、サブセット化しないなど、その結果としてメガバイト単位のフォントデータがページレンダリングをブロックしてしまいます。日本語の場合、デフォルトのNoto Sans JPファイルは数MBにもなり、サブセット化なしではページ上で最も大きなアセットになることすらあります。
より微妙な問題もあります。AIエージェントはデフォルトで見出しにfont-weight: bold、本文にfont-weight: normalを使いがちです。しかし、Noto Sansの広いウェイト幅が可能にする、より洗練された階層構造を見逃しています。例えば、本文をLight(300)にして見出しをRegular(400)にする、または本文をRegular(400)にして見出しをMedium(500)にするといったアプローチは、太字と通常体のコントラストだけでなく、ウェイトの差による視覚的な差別化を生み出します。
解決方法
Noto Sansは、慎重なウェイト選択、適切なサブセット化、font-display: swapを使って読み込みます。フォントスタックをCSSカスタムプロパティとして定義して一貫して再利用し、単に太字と通常体を使うのではなく、目指す階層を実現するウェイトを選びましょう。
コード例
Google Fonts CDN経由での読み込み
最もシンプルな方法です。Google Fontsはサブセット化を自動的に処理し、リクエストで検出された言語に必要なグリフだけを返します。
<!-- 効率的: 必要なウェイトだけをリクエストする -->
<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@300;400;500&display=swap"
rel="stylesheet"
/>
:root {
--font-noto: 'Noto Sans JP', 'Noto Sans', ui-sans-serif, system-ui,
-apple-system, 'Hiragino Sans', sans-serif;
}
body {
font-family: var(--font-noto);
font-weight: 300; /* Light — 本文テキストに余白感を生む */
}
h1,
h2,
h3 {
font-family: var(--font-noto);
font-weight: 400; /* Regular — 本文より目立ちつつ太字になりすぎない */
}
@fontsource経由での読み込み(セルフホスト)
@fontsourceパッケージを使うとサブセット化してセルフホストできます。必要なウェイトだけをインストールしましょう:
# Noto Sans JPをインストール — ウェイト300と400のみ
npm install @fontsource/noto-sans-jp
/* 実際に使うウェイトだけをインポートする */
@import '@fontsource/noto-sans-jp/300.css';
@import '@fontsource/noto-sans-jp/400.css';
@import '@fontsource/noto-sans-jp/500.css';
Next.jsのnext/font/google経由での読み込み
Next.jsのnext/font/googleはフォントを自動的に最適化します。セルフホスト化し、外部リクエストをなくし、クリティカルなCSSをインライン化します。
import { Noto_Sans_JP } from 'next/font/google';
const notoSans = Noto_Sans_JP({
weight: ['300', '400', '500'], // 使うものだけ読み込む
subsets: ['latin'],
variable: '--font-noto',
display: 'swap',
});
export default function RootLayout({ children }) {
return (
<html lang="ja">
<body className={notoSans.variable}>{children}</body>
</html>
);
}
body {
font-family: var(--font-noto), 'Hiragino Sans', sans-serif;
}
Docusaurusでの読み込み
Docusaurusでは、フォントリンクをdocusaurus.config.tsに追加し、custom.cssで適用します:
// docusaurus.config.ts
const config = {
headTags: [
{
tagName: 'link',
attributes: {
rel: 'preconnect',
href: 'https://fonts.googleapis.com',
},
},
{
tagName: 'link',
attributes: {
rel: 'preconnect',
href: 'https://fonts.gstatic.com',
crossorigin: 'anonymous',
},
},
{
tagName: 'link',
attributes: {
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@300;400;500&display=swap',
},
},
],
};
/* src/css/custom.css */
:root {
--ifm-font-family-base: 'Noto Sans JP', 'Noto Sans', ui-sans-serif,
system-ui, -apple-system, 'Hiragino Sans', sans-serif;
--ifm-font-weight-base: 300;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 400;
}
フォントウェイト階層のパターン
全ウェイトのウェイト比較
CSS変数を使ったフォントスタック管理
パフォーマンス:日本語フォントのサブセット化
Noto Sans JPはすべての日本語文字をカバーしているため、フルフォントファイルは大きくなります(数MB)。Google Fontsはページ上のテキストに基づいて自動的にサブセット化して処理します。セルフホストのフォントには、unicode-rangeを使ってスクリプト別にファイルを分割できます:
/* ラテン文字 — 小さいサブセット */
@font-face {
font-family: 'Noto Sans JP';
src: url('/fonts/noto-sans-jp-latin.woff2') format('woff2');
font-weight: 300;
font-display: swap;
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215;
}
/* 日本語文字 — 大きいファイル。日本語テキストがある場合のみ読み込まれる */
@font-face {
font-family: 'Noto Sans JP';
src: url('/fonts/noto-sans-jp-japanese.woff2') format('woff2');
font-weight: 300;
font-display: swap;
unicode-range: U+3000-9FFF, U+F900-FAFF, U+FF00-FFEF;
}
display=swapがすでに付いたGoogle FontsのURLを使う場合、このURLのアプローチが自動的に処理してくれるため、unicode-rangeを手動で管理する必要はありません。
AIがよくやるミス
- デザインで2〜3ウェイトしか使わないのに9ウェイトすべてを読み込む(
wght@100;200;300;400;500;600;700;800;900)— 帯域を無駄にし、日本語フォントではページの読み込みが大幅に遅くなる - Google FontsのURLに
display=swapを指定しない — 低速な接続でFOIT(Flash of Invisible Text)が発生する - 本文が
font-weight: normal(400)なのに見出しにfont-weight: bold(700)を使う — 大きな段差が生まれる。300/400や400/500のように、より小さいウェイト差を使う方が洗練されている - Google Fontsの
<link>の前にpreconnectヒントを含めない — フォントリクエストへの不要なレイテンシが生じる - 日本語テキストがあるページで、JPバリアントなしで
'Noto Sans'だけを参照する — ベースのNoto Sansには日本語グリフが含まれていない - CSS変数を使わずフォントファミリーの文字列をフラットに書く — コードベース全体でフォントスタックを一貫して変更しにくくなる
- サブセット化せずにNoto Sans JPをセルフホストする — ウェイトあたり4〜8MBになることがあり、サブセット化処理なしではセルフホストは現実的でない
使い分け
Light本文(300) + Regular見出し(400)
- 長文コンテンツ、エディトリアルサイト、ドキュメント
- エレガントで洗練された外観を目指すデザイン
- 明るい背景に暗い文字のカラースキームで視覚疲労を軽減したい場合
Regular本文(400) + Medium見出し(500)
- UIが多いアプリケーション、ダッシュボード、管理画面
- 情報密度が高く、明確な階層が重要なデザイン
- 本文と見出しの両方を小さいサイズでも読みやすくしたいページ
Noto Sans JPを特に使う場合
- 日本語、韓国語、CJK文字を含むページ
- スクリプト間で一貫したレンダリングが必要な多言語サイト
- 個性的なデザインの声よりも、中立的で高い可読性を持つ書体を好むプロジェクト