modular-scale-typography について
デザイナーやフロントエンド開発者向けのタイポグラフィガイドです。基準サイズと比率から文字サイズのスケールを作り、画面上の読みやすさや字間、改行も扱います。
主な機能
- 01基準サイズと比率からスケールを生成
- 02CSS と Tailwind のトークンに変換
- 03ページの用途に応じたサイズ選択
- 04字間、ウェイト、数字の整列
- 05改行ルールとレイアウトによるはみ出し対策
活用シーン
- 01UI の文字階層を統一
- 02CSS や Tailwind にスケールを設定
- 03小さい文字の読みやすさを確認
- 04見出し、段落、ラベルの改行を調整
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dembrandt/ dembrandt-skills --skill modular-scale-typographyインストール後、Claude Code で/modular-scale-typographyを入力して読み込まれたか確認します。
詳細
モジュラースケールのタイポグラフィ
すべてのフォントサイズが、単一の数学的な比率によって相互に関連付けられていると、タイポグラフィに一貫性が生まれます。スケールがないと、サイズは恣意的に選ばれ、見た目にまとまりがなくなります。見出しのコントラストが足りない、本文とキャプションのサイズが近すぎる、ラベルがコンテンツに溶け込む、といった問題が起こります。
モジュラースケールとは
モジュラースケールでは、基準サイズを起点にして、比率を掛けたり割ったりすることで、システム内のすべてのサイズを生成します。
size(n) = base × ratio^n
つまり、すべてのサイズは基準から意図的に段階を踏んだものであり、推測で決めるものではありません。
比率の選択
| 比率 | 名称 | 印象 | 適した用途 |
|---|---|---|---|
| 1.067 | マイナーセカンド | 非常に小刻み | データが密集した UI、ダッシュボード |
| 1.125 | メジャーセカンド | 控えめ | 長文の読み物、エディトリアル |
| 1.200 | マイナーサード | バランスがよい | ほとんどの UI アプリケーション |
| 1.250 | メジャーサード | 明確な階層 | マーケティング、ランディングページ |
| 1.333 | パーフェクトフォース | 強いコントラスト | ディスプレイ、ヒーローセクション |
| 1.414 | オーグメンテッドフォース | 劇的 | ポートフォリオ、ブランディング |
| 1.500 | パーフェクトフィフス | 非常に劇的 | 控えめに使用 |
デフォルトの推奨値: 1.25(メジャーサード)。大げさにならず、各段階に意図を感じられるだけのコントラストが得られます。
スケールの生成
既存のスケールは手作業で逆算せず、復元してください(dembrandt エンジン、任意)。 ブランドのタイポグラフィがすでにウェブ上にある場合、
get_typographyを使うと、実際の DOM から算出されたフォントサイズ、ウェイト、行の高さを取得できます。それらから基となる比率を推定し、サイズを推測するのではなく、以下の方法で規則化してください。extract-designを参照してください。
base = 16px、比率 1.25 から始めます。
| 段階 | 計算式 | 値 | 丸めた値 | 用途 |
|---|---|---|---|---|
| -2 | 16 ÷ 1.25² | 10.24px | 10px | キャプション、label-xs |
| -1 | 16 ÷ 1.25 | 12.80px | 13px | ラベル、小 |
| 0 | 16 | 16px | 16px | 本文(基準) |
| +1 | 16 × 1.25 | 20px | 20px | body-lg、リード |
| +2 | 16 × 1.25² | 25px | 25px | H4 |
| +3 | 16 × 1.25³ | 31.25px | 31px | H3 |
| +4 | 16 × 1.25⁴ | 39.06px | 39px | H2 |
| +5 | 16 × 1.25⁵ | 48.83px | 49px | H1 |
| +6 | 16 × 1.25⁶ | 61.04px | 61px | ディスプレイ |
整数のピクセル値または rem に丸めてください。比率によって意図は保たれるため、ピクセル値を厳密に丸めても問題ありません。
デザイントークン(CSS カスタムプロパティ)
:root {
--text-xs: 0.625rem; /* 10px — caption */
--text-sm: 0.813rem; /* 13px — label */
--text-base: 1rem; /* 16px — body */
--text-lg: 1.25rem; /* 20px — lead */
--text-xl: 1.563rem; /* 25px — h4 */
--text-2xl: 1.938rem; /* 31px — h3 */
--text-3xl: 2.438rem; /* 39px — h2 */
--text-4xl: 3.063rem; /* 49px — h1 */
--text-5xl: 3.813rem; /* 61px — display */
}
Tailwind の設定
// tailwind.config.js
fontSize: {
'xs': ['0.625rem', { lineHeight: '1rem' }],
'sm': ['0.813rem', { lineHeight: '1.25rem' }],
'base': ['1rem', { lineHeight: '1.5rem' }],
'lg': ['1.25rem', { lineHeight: '1.75rem' }],
'xl': ['1.563rem', { lineHeight: '2rem' }],
'2xl': ['1.938rem', { lineHeight: '2.25rem' }],
'3xl': ['2.438rem', { lineHeight: '2.5rem' }],
'4xl': ['3.063rem', { lineHeight: '1.1' }],
'5xl': ['3.813rem', { lineHeight: '1' }],
}
タイポグラフィに一貫性が生まれる理由
スケールがない場合、デザイナーや開発者は目分量や慣例でサイズ(14px、16px、18px、24px、32px、48px)を選びます。間隔にばらつきがあるため、これらのサイズは微妙にしっくりきません。14→16 の差は小さい一方、32→48 の差は大きく、それらを結び付ける根本的な論理もありません。見る人がその理由を言葉にできなくても、目には一貫性のなさが伝わります。
モジュラースケールを使うと、サイズが一段階変わるたびに、視覚的に同じ重みの変化が生まれます。各レベルが恣意的な間隔ではなく、次のレベルから比例した段階にあるため、階層が明確に伝わります。
最小フォントサイズ
本文の基本サイズ:最低16px。 これがブラウザーのデフォルトであるのには理由があります。これを下回ると、特に画面上では読みやすさが大きく損なわれます。
- 16px — 標準の本文テキスト、デフォルトの基本サイズ
- 14px — 二次的な UI テキスト(ラベル、キャプション、メタデータ)に限り、控えめに使うのであれば許容範囲です
- 14px未満 — 使用しないでください。高 DPI であっても、14px未満のテキストは通常のテキストに関する WCAG のコントラスト要件を満たせず、アクセシビリティ上の問題を引き起こします。
モジュラースケールでは、基本サイズ(step 0)を16pxにし、負のステップ(step -1、step -2)は本当に二次的なコンテンツにだけ使用することを意味します。本文や主要なラベルには決して使用しないでください。
1%の経験則。 16px未満のテキストは例外的なものです(目安はページの約1%未満、最低でも14px)。文字数を数える人はいないため、役割で判断してください。
- 16px未満でもよいもの — ちらっと見るだけの役割に限った固定リスト:タイムスタンプ、キャプション、表のメタデータ、補助テキスト、注意書き、バッジのラベル。
- 決して使用しないもの — 本文、主要なラベル、リスト項目のタイトル、タスクを遂行するために実際に読むもの。
確認方法:1画面を見渡し、16px未満の役割の種類を数えます。リストにあるものが2、3種類なら適切です。5種類以上、または読む必要のあるコンテンツがあれば、縮小しすぎです。それはレイアウトの密度の問題であり、文字の問題ではありません。文字を縮めて収めるのではなく、表示内容を減らしてください。
文字表示の詳細
サイズと比率が構造を決めます。次の詳細によって、画面上で文字が実際に読みやすくなるかどうかが決まります。
文字間隔
- 本文とデフォルトのテキスト: トラッキングは
0に保ちます。通常の文章に加えると読む速度が落ち、文字が間延びして見えます。 - 大文字と小さなラベル: 大文字は視覚的に詰まって見えるため、トラッキングが役立つ唯一の場面です。上限は
0.04emとし、ラベルに本当に余裕が必要な場合だけ使用してください。 - パターン:小文字の本文はゼロ、大文字のラベルはわずか(
≤ 0.04em)まで — 全体に一律で適用しないでください。トラッキングを広げすぎると、上質というより古びて見えます。
大文字ラベル周辺の視覚的な余白
すべて大文字のラベルやディセンダーのないラベルでは、行ボックスの下部に空きが生じます。上下のマージンを同じにすると、インスペクター上では同じ大きさでも、下側のほうが広く見えます。ボックスではなく、目に見える字形から余白を測り、上下が同じに見えるまで下側の余白を数ピクセル減らしてください。間隔が「ずれている」のに理由を説明できないときに起きているのは、これです。
暗い背景でのウェイト
暗い背景に置かれた明るい文字は、視覚的に細く見えます。これは明るい文字が暗い背景ににじむハレーション効果によるものです。補うためにウェイトを1段階上げます。明るい背景でレギュラー(400)が適切なら、暗い背景では同等のテキストにミディアムまたはセミボールドを使用してください。これにより、ダークモードの文字が弱々しく見えることなく、モード間で見た目のウェイトを一貫させられます。
等幅フォント
等幅フォントは、コード、ID、数値表、差分など、文字の位置合わせが重要な技術コンテンツに使用します。UI のデフォルト書体としては使わず、等幅フォントと大文字の組み合わせも避けてください(文字幅が均一で大文字の背が高いため、ざっと見て把握しにくくなります)。
表示中に変化する数値
カウンター、カウントダウン、更新される価格、数値の列などでは、プロポーショナル数字は数値ごとに幅が異なるため、更新のたびにテキストが左右に揺れ、列も揃わなくなります。数字が更新されたり、縦に並んだりする場所ではタブラ数字に切り替えてください。タブラ数字は間隔が空いて見えるため、本文ではプロポーショナル数字のままにします。
.stat, .price, td.numeric { font-variant-numeric: tabular-nums; }
行の折り返し位置
見出しは、折り返し位置を調整する場所です。text-wrap: balance は短い見出しの行の長さを整え、最後の行に1語だけ残るのを防ぎます。text-wrap: pretty は孤立した語を防ぐだけなので、段落にはこちらのほうが負荷の低い選択肢です。ブラウザーは balance の対象を数行に制限しているため、これは見出し向けであり、本文向けではありません。
この種の要素すべてに対して、スタイルシートで一度だけ設定してください。コンポーネントに text-balance ユーティリティを散りばめても、そのコンポーネントにしか適用されず、次に誰かが作るページではいつの間にか適用されなくなります。
h1, h2, h3, h4, h5, h6,
figcaption, blockquote, dt { text-wrap: balance; }
p, li, dd { text-wrap: pretty; }
3つのブラウザーすべてで balance が機能しますが、pretty に対応しているのは Chrome と Safari だけです。どちらもレイアウトの成立に不可欠なものではありません。balance の対象は Chrome では6行、Firefox では10行までなので、本文には決して使わないでください。タイトル、トースト、ツールチップ、キャプション、折り返されるボタンも単語が取り残されることがあるため、同じルールにクラスで追加してください。Balance はボックスではなく折り返し位置を変えるので、左揃えの見出しには、まず ch 単位で max-width を設定してください。
ウィドウを直すために、<br> を手動で入れて改行するのはやめてください。あるビューポート幅では正しくても、それ以外の幅では不適切になります。コンポーネントごとの折り返しは、デザイナーが求める意図的な例外であり、デフォルトで選ぶ方法ではありません。
改行されないスペースで語句を後続の語句に結び付けます。たとえば、10 kg、Figure 3、人名とその肩書きです。単位だけが次の行に取り残されると、誤植のように見えます。
表示領域に収まらないテキスト
text-wrap: balance は、見出しの不自然な折り返しを直します。配置先の領域に対してテキストが長すぎる問題は解決しません。そこでこれに頼ると、あるビューポート幅でだけ本当の問題を隠し、次の幅で再発させてしまいます。
行末に1語だけ取り残される場合や、タイトルの横でキャプションが3行に折り返される場合、適切な対処法は次の3つだけです。
- テキストを短くします。 通常はこれが正しい方法です。ラベル用に設計された領域が求めているのは、文章ではありません。
- サイズを1段階下げます。 タイトルの横に置く補足テキストは、同じサイズではなく、1〜2段階小さくするべきです。
- 親のレイアウトを変更します。 意味を伝えるのに必要なところまでテキストをすでに短くしているなら、問題はコンテナーにあります。そのブレークポイントでグリッドの列を減らす、列幅を広げる、専用の行にする、位置を変えるなどの方法があります。幅1280pxのビューポートにタイルを6つ横並びにすると、それぞれの幅は約190pxになり、数値、ラベル、キャプションをすべて収めるのは、どんな言い換えでも無理です。同じ幅で3つ並べれば収まります。
順序が重要です。最初の2つの方法を試し尽くしてからレイアウトに手を付けてください。先にレイアウトを変更すると、本来3語で済む文章を救うためにコンテナーを広げることになり、同じ問題が次のブレークポイントに移るだけです。
修正にならないのは、そのまま放置することや、今見ている幅にたまたま収まるまでコンテナーを微調整することです。
凡例は文章ではありません。「棒の高さは合計で、塗りつぶされた部分は完了した数です」という説明は、3語程度の見出し用に設計された場所には長すぎます。折り返され、最後の行に1語だけが残ります。色見本を2つ使い、それぞれに1語を添えれば、同じ意味を伝えつつ、不自然に折り返されることもありません。
■ completed □ total
軸ラベル、表の見出し、チップのテキスト、大きな要素の横に置くキャプションにも、同じことが当てはまります。説明に本当に文章が必要なら、その要素の横ではなく下に置いてください。
1つのスロットにある2行
説明文が付いたラベルは2つの役割を持つため、2つの役割として見える必要があります。同じサイズ、ウェイト、色では、どちらの役割も伝わらない1つのグレーの塊に見えてしまいます。
<div class="w-36">
<div class="text-sm font-medium text-gray-500 truncate">Imported</div>
<div class="text-sm font-medium text-gray-500 truncate">rows without a matching account are skipped</div>
</div>
サイズではなく、ウェイトとインクで区別してください。これは、上記の「異なる役割は距離を置く」という原則の例外です。どちらの行もすでに14pxの下限に近いため、2行目を1段階小さくすると最小サイズを下回り、2段階離してもこのサイズではほとんど違いが見えません。プライマリのセミボールドと、ミュートしたミディアムの組み合わせで十分です。また、ミュート色には独自の下限が必要です。パレットで最も薄くても判読できる色を最も軽いウェイト(400)と組み合わせると、色だけのWCAGコントラストは満たしていても判読不能に見えます。コントラストの計算は色のみを対象とし、線のウェイトは考慮しないためです。ミュート/セカンダリのテキストトークンは、ここだけでなく、どこで使う場合も最低ウェイトを500にしてください。
説明文は省略しないでください。 名前は最初の文字から読み手が認識できるため、途中で切れても意味が残ります。しかし、文章はそうではありません。切り取られるのは意味を伝える部分であり、それをtitle属性に移すと、タッチ操作やキーボード操作では見えず、ホバーしようと思わない人にも伝わりません。そのため、下記の「行のクランプ」にあるtitle属性を使う回避策は、ユーザーが操作する必要のない補足説明に限られています。付随する対象の意味を伝える説明文には決して使わないでください。識別子は省略して構いません。説明文は折り返すか、短くするか、列の幅を広げてください。
ページのコンテキストに応じた文字サイズのスケール
ランディングページやマーケティング向けの画面では、大きく表現力のある文字が効果的です。見出しを+4〜+6段階にすると、ドラマチックな印象とブランドの存在感が生まれます。
機能ページやアプリケーションのUIでは、より抑えた範囲を使います。見出しは+2〜+3段階、本文は0段階にします。機能的なUI内の大きすぎる見出しは、コンテンツの邪魔になり、レイアウトのバランスを損ないます。
ブランドだけでなく、画面の目的に合わせて比率とスケールの使い方を調整してください。
1つのビューにつき4段階。 1つのビューとコンテキストの中では、パネル、オーバーレイ、ページ領域を問わず、スケールを4段階以内にしてください。4という数は好みの境界ではなく、1つのビューにある文字の役割の数です。つまり、タイトル、本文、ラベル、メタデータです。この上限は役割の数から導かれています。そのため、5段階目が必要に思えるビューは、実際には誰も名付けていない5つ目の役割を持っています。それを名付ければ、通常は別のビューに属するか、レイアウトにまだ描かれていないグループに属することが明らかになります。サイズを1つ増やすごとに階層についての主張も増え、4段階を超えると目が順位を付けられなくなるため、隣接する段階が階層ではなく誤りのように見えます。これは、下記の「3つのルール」が見出しのレベルについて述べているのと同じ考え方です。こちらは画面上の文字のサイズについての話であり、ビュー内の見出しレベルが1つだけでも、4サイズの上限に達することがあります。
見出しの階層とページの複雑さ
適切な見出しのスケールでは、レベルの区別にフォントサイズだけを使いません。また、ページが扱える認知的な限界も尊重します。
見分けるための手法
見出しの違いがわずかなサイズの差だけだと、ひと目で区別しにくくなります。より意味のあるスケールを作るには、次の手法を使ってください。
- 大文字表記: 小さめの下位見出し(H4〜H5)には大文字表記(
text-transform: uppercase)を使い、サイズを大きくしなくても視覚的な重みを持たせます。 - 字間: 大文字表記や太字の見出しを使う場合、
letter-spacingはごくわずか(≤ 0.04em)にとどめ、見出しに本当に余裕が必要な場合だけ加えてください。控えめに保ちます。字間を広げすぎると、上質ではなく時代遅れの印象になります。 - 色: ブランドのプライマリカラーか、少しミュートしたグレーを使い、セカンダリ見出しを本文の黒/ダークグレーのテキストから区別します。
- スタイル: 補足情報やメタデータ風の見出しには、イタリック体や控えめな下線を使います。
3段階の見出し階層(H1〜H3)
適切に設計されたページのほとんどは、**3段階の見出し階層(H1、H2、H3)**だけで十分です。
- シンプルさ: H1〜H3で、ページタイトル、セクションタイトル、サブセクションをすべてカバーできます。
- H4〜H6が必要なのは、タイポグラフィの問題ではなく、複雑さの兆候です。 H4、H5、H6を使いたくなったら、そのページは詰め込みすぎです。見出しレベルをさらに細かくしても、症状が隠れるだけです。これをシグナルとして受け止め、代わりに構造上の判断をしてください。
- 分割する — 実際には2つの機能、あるいはページ内のサブページに相当する内容です。ページを分けるか、モジュール式の構成(サイドバー、タブ、マスター・ディテール)に分けます。
- 削除する — 深い階層のセクションは、そもそも必要ないかもしれません。
- 簡素化する — サブ階層をフラット化し、H1〜H3に収まるようにします。
- 開閉式の要素の中に隠す — 補足的な内容をモーダル、アコーディオン、パネルの中に移します(
information-architectureを参照してください)。
見出しが6段階も必要なページは、ほとんどのユーザーが読むのをやめてしまうページです。
読みやすさと編集パターン
タイポグラフィは、文字の大きさだけではなく、コンテンツのリズムと構造にも関わります。
行の長さ(字詰め)
読みやすさを最適にするには、本文の1行を45〜75文字(約500〜700px)に保ちます。
- 行が長すぎると、次の行の先頭を見つけにくくなります。
- 行が短すぎると、読書のリズムが崩れ、行末の不揃いが気になります。
字詰め、行送り、文字サイズは連動します
行の長さ、行の高さ(行送り)、文字サイズは、それぞれ独立した調整項目ではなく、ひとつのシステムです。これは基礎的なタイポグラフィの原則(BringhurstのThe Elements of Typographic Style)であり、デジタルプラットフォームで繰り返し検証されています。また、MaterialとApple HIGの文字サイズスケールにおける行の高さの段階設定の基盤でもあります。
字詰めが広いほど、目線を次の行頭へ戻すために、より広い行送りが必要です。 狭い段組みでは問題なく読める行間も、広い段組みでは疲れやすくなります。
| 字詰め | 推奨される本文の行の高さ |
|---|---|
| 狭い(約45ch) | 1.4 |
| 快適(55〜66ch) | 1.5 |
| 広い(約75ch) | 1.6〜1.7 |
実践的なルール:
- 本文: 行の高さは1.4〜1.7とし、複数行の文章では1.4未満にしません。WCAG SC 1.4.12では、ユーザーが行の高さを少なくとも1.5に変更しても、テキストが読みやすい状態であることも求められているため、それを見越して設計してください。
- 見出し: 大きな文字ほど、行送りは狭くします。サイズが大きくなるにつれて1.1〜1.25に詰めないと、行が離れすぎてひとまとまりとして読めなくなります。行送りと文字サイズは反比例します。
- 症状ではなく原因を解消する: 本文の行が読みにくいと感じたら、行送りを広げるか字詰めを狭くします。文字を小さくするだけでは解決しません。この3つは連動します。
行数制限
グリッド、カード、リストなど、コンテンツの長さが予測できない場合は、テキストの行数を制限して、視覚的なリズムを一定に保ち、カードの高さをそろえます。説明文を2~3行に制限すれば、同じ行のカードの高さがそろいます。
複数行の制限。 標準のline-clampと-webkit-のフォールバックを組み合わせます。すべてのブラウザーをサポートするには、旧式の-webkit-box形式も引き続き必要なため、両方を使用してください。
.card-description {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
line-clamp: 3;
overflow: hidden;
}
1行の制限。 折り返しを許可しないタイトルやラベルには、代わりに省略記号のパターンを使用します。
.card-title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
フレックスやグリッド内の場合。 アイテムがコンテンツ幅より小さく縮められないと、切り詰めは何も表示せずに失敗します。制限する子要素にmin-width: 0(またはmin-inline-size: 0)を指定し、幅を縮められるようにします。
アクセシビリティ — コンテンツを見失わせない。 行数制限で隠れるのは視覚的にのみです。文字列全体はDOM内に残り、スクリーンリーダーでは全文が読み上げられますが、視覚で内容を確認するユーザーには見えなくなります。残りの内容を確認できる手段を必ず用意してください。
- 全文を含む
title属性(またはアクセシブルなツールチップ)を指定する、または - 完全なコンテンツを表示する詳細ビューや「続きを読む」へのリンクを設ける。
この代替手段は、ユーザーが行動を起こすうえで読む必要のない補足説明に限ります。省略された部分に意味がある説明には適用できません。上記の「説明を途中で切り詰めない」を参照してください。
行動を起こすためにユーザーが必ず読む必要があるテキスト(価格、エラー、法的文言、主な手順)は、決して行数制限しないでください。切り詰めても問題のない補足説明にのみ適用します。
固定サイズのページ。 overflow: hiddenを使用した固定ページで構成されるドキュメント(印刷、PDF、A4プレビュー)では、レンダラーが測定したコンテンツでページを埋めた後に追加されたテキストは、ページ下部に配置され、どのページにも印刷されませんが、エラーも発生しません。生成または作成されたコピーには、フッターより上に収まるボックスを設けて専用のページを割り当て、折り返しが行われるブラウザーで行数制限を適用します。文字数の上限ではページの終わりを予測できません。分かるのはレイアウトエンジンだけです。
編集上の階層
役割ごとに異なるタイポグラフィを使い、コンテキストを示して、ユーザーがストーリーを読み進められるようにします。
| 役割 | 視覚的なスタイル | 目的 |
|---|---|---|
| 前置きタイトル(アイブロウ) | 小さめ(12~13px)、大文字表記が多い、控えめな文字間隔(≤ 0.04em)、落ち着いた色 | メインの見出しを目立たせたまま、コンテキストやカテゴリーを示します |
| 見出し | 大きく太字で、モジュラースケールの+3~+5段階 | 主な訴求点やテーマを示します |
| 導入文(リード文) | 本文より大きめ(+1段階)で、やや太字、または行の高さを大きめに設定 | 中核となる価値を要約し、見出しと本文をつなぎます |
| 本文 | 基本サイズ(16px)、標準の太さ、読みやすい行の高さ(1.5) | 主な読書体験を提供します |
文言と語調
- 能動態を使います。 「始めるのは簡単です」ではなく「始めましょう」。
- 簡潔に伝えます。 成果が分かる、明確で具体的なラベルを使います。
- 一貫性を保ちます。 製品全体で、同じ操作には同じ用語を使います。
レスポンシブな文字サイズのスケール
小さなビューポートでは、個々のサイズを手動で上書きするのではなく、比率を狭めることでスケールを圧縮します。下限の本文やラベルは読みやすさの最低基準として固定します。上限のH1やディスプレイサイズは大幅に縮小します。比率が変わるため、すべての見出しレベルが比例して変化し、階層の一貫性が保たれます。
ルール: デスクトップでは広い比率(より強いメリハリ)、モバイルでは狭い比率(より控えめ)を使います。基本サイズは変えず、上限側を縮小します。
- デスクトップ → 広い比率(例:1.25~1.333)。H1と本文に大きな差をつけます
- タブレット → 中程度の比率(例:1.200)。スケールを縮めます
- モバイル → 狭い比率(例:1.125)。H1はかなり小さくなりますが、本文は変わりません
スケールを下限側から縮小しないでください。16pxの本文はすでに下限です。圧縮する場合は、常に上限側から行います。
clamp() を使った流動的な文字サイズ
固定のブレークポイントごとにサイズを切り替えるのではなく、CSS の clamp(MIN, PREFERRED, MAX) を使い、下限と上限の間で文字サイズを滑らかに拡大縮小します。中間のビューポート相対値で拡大縮小し、下限と上限によって小さくなりすぎたり大きくなりすぎたりするのを防ぎます。
:root {
--text-body: 1rem; /* the floor stays fixed */
--text-h1: clamp(2rem, 1.5rem + 3vw, 3.5rem);
}
MINはモバイルサイズ、MAXはデスクトップサイズです。段階的なスケールと同じく、下限と上限を設定し、その間を補間します。clamp()はスケールの上部(見出し、ディスプレイテキスト)に適用します。本文とラベルは固定サイズにします。読みやすさには最低限のサイズが必要なので、下限を動かしてはいけません。- 推奨値には
remの項を含めます(例:3vwだけではなく1.5rem + 3vw)。そうすれば、ユーザーのズームやルートフォントサイズにもテキストが反応し続けます。vwだけの値ではズーム時のアクセシビリティが損なわれます。
隣り合う流動的なステップは同じサイズに近づくことがあります
デザインシステムで複数の小さなステップ(text-fluid-xs、text-fluid-sm など)まで流動的なサイズにする場合、隣り合う2つのクランプサイズがビューポート幅の範囲全体で常に差を保てるとは限りません。それぞれの clamp() は、個別の下限と上限の間を独自の傾きで補間します。そのため、vw の係数が異なる2つのステップは、最小幅と最大幅では正しく間隔が空いて見えても、途中の幅で互いに近づいたり、計算後の値が完全に同じになったりすることがあります。両端だけを確認しても、この問題は見つかりません。重要なのは端点での間隔ではなく、範囲全体での最小の間隔です。
/* Looks fine at 375px and 1440px. At ~860px both resolve to ~14.9px. */
--text-fluid-xs: clamp(0.75rem, 0.65rem + 0.4vw, 0.875rem);
--text-fluid-sm: clamp(0.8125rem, 0.7rem + 0.45vw, 0.9375rem);
- 隣り合う小さなステップは、そもそも流動的なサイズにしないでください。 これは上記の「本文とラベルは固定サイズにする」というルールが実際に守られないケース、つまり本文のすぐ隣にキャプションがある場合や、ラベルサイズのステップが隣り合う場合について述べたものです。サイズの差が縮まらないように、固定サイズを使います。
clamp()はスケールの上部に限定します。同じ行で見出しが別サイズのテキストとピクセル単位で隣り合うことは、ほとんどありません。 - 小さなステップを流動的なサイズにする必要がある場合は、 MIN と MAX だけでなく、範囲全体で間隔を確認します。中間の幅をいくつか選んで2つの値を計算するか、両方の
clamp()式をグラフにして、確認したブレークポイントだけでなく、その間のどこでも、値が交差したり、間隔が数 px 以内まで縮まったりしないことを確かめます。 - 係数は共通化するのがおすすめです。 隣り合う流動的なステップの
vw係数を比例関係にすると(例:同じモジュラ比から導出する)、個別に選んだ傾きが交差するのを防ぎ、曲線を平行に保てます。
読み取り用テキストはすべて 16px を優先します
ヒント、メタデータ、キャプション、HUD ラベルも読むテキストなので、本文と同じ 16px を基本とします。まずウェイト、色、間隔で階層を作り、それらを活用しきった場合にのみサイズを小さくします。セカンダリテキストも 14px 未満にはしません。ベースサイズより小さくする各ステップは、セカンダリと呼ばれるものすべてに適用する標準ではなく、意図的な例外です。
レビューチェックリスト
- すべてのフォントサイズは、単一のベースサイズと比率から導出されていますか?
- ベースサイズは16px以上ですか?
- 14pxは補助テキスト/メタデータのみに使用し、本文には使用していませんか?
- UI内のどこにも14px未満のサイズを使用していませんか?
- 画面上の16px未満のテキスト役割の種類を数えたとき、補助テキストの許可リストに含まれるものだけが少数(≤3)あり、読ませるコンテンツには使われていませんか?
- 本文の文字間隔は0で、大文字ラベルのトラッキングは
0.04em以下に抑え、余白が必要な場合にのみ使用していますか? - 暗い背景に明るい文字を使う場合、ハレーションを補うためにやや太いウェイトを使っていますか?
- すべて大文字のラベルの周囲の間隔は、行ボックスではなく、見えている字形を基準に調整されていますか?
- 等幅フォントは技術的なコンテンツに限定し、デフォルトや大文字表記には使用していませんか?
- 本文から最大の見出しまでに、少なくとも3~4段階の明確な差がありますか?
- 隣接する段階(例:本文とラベル)は、一目で見分けられるだけの差がありますか?
- フォントサイズのトークン名は、生のピクセル値ではなく、役割(
--text-body、--text-h1)または段階(--text-base、--text-2xl)で付けられていますか? - 選択した比率はUIの密度に適していますか?(データ量の多いUIでは狭い比率、マーケティングでは広い比率)
- 本文の1行の長さは45~75文字ですか?
- タイトル横の補助テキストが折り返されたり、単語だけが1行に取り残されたりしていませんか?短くするか、サイズを一段階下げるか、十分な幅を確保してください。そのままにしてはいけません。
-
text-wrap: balanceは見出しと短文用のクラスに一度だけ設定し、本文には適用していませんか? - 凡例、軸ラベル、チップのテキストは、文ではなくラベルとして記述されていますか?
- テキストを短くしても収まらない場合、さらにテキストを詰め込むのではなく、そのブレークポイントでの列数を見直していますか?
- ラベルと説明を同じ枠内に縦に並べる場合、同じグレーの行を二つ並べるのではなく、ウェイトと色味に差をつけていますか?
- 省略表示は識別子にのみ使用し、切り取られる部分に意味が含まれる説明には使用していませんか?
- 本文の行高は行長に応じて調整され(狭い場合は≈1.4、広い場合は≈1.6以上)、1.4以上を維持しつつ、WCAG 1.4.12に対応する1.5への上書き余地を確保していますか?
- 見出しはサイズが大きくなるほど行間を詰め(≈1.1~1.25)、大きな文字でもひとまとまりとして読めるようにしていますか?
- グリッド/カードのレイアウトを揃えるために、行数制限を使用していますか?
- 行数制限されたテキストには、完全な内容を確認できる手段(
title/ツールチップ、または詳細表示)があり、必読の内容には行数制限を使用していませんか? - 可変フォントサイズ(
clamp())を使用する場合、スケールの上位部分だけに適用し、ズームが機能するように優先値にはremベースの値を使っていますか? - 隣接する二つの段階を両方とも可変にする場合(例:
xs/sm)、MIN/MAXの端点だけでなく、ビューポート範囲全体で視覚的な差が保たれていますか? - プリタイトルやリード文などのエディトリアル向けの役割を、読み取りやすさの向上に活用していますか?
- 見出しはサイズ以外の要素(例:色、大文字・小文字、間隔)でも区別されていますか?
- 可能な限り、ビューごとの見出し階層はH1~H3に限定されていますか?
- ヒントやメタデータを含む閲覧用テキストは、デフォルトで16pxになっていますか?また、サイズより先にウェイトと色で階層を表現し、14px未満のサイズは使用していませんか?
よくあるアンチパターン
| アンチパターン | 問題 | 修正方法 |
|---|---|---|
| 14、15、16、17pxのようなサイズを並べて使用する | 段階の違いが小さすぎて、別々のレベルとして認識しにくい | 各段階を認識できるよう、少なくとも1.125の比率を使用します |
| 相互に関連のない任意のサイズ(13、18、27、36px)を使用する | 基本となる規則がなく、階層が場当たり的に感じられます | 単一の基準値と比率から再生成します |
| トークンではなく、コンポーネントにピクセル値を直接ハードコードする | スケールの変更時に、すべてのファイルをくまなく探す必要があります | CSS カスタムプロパティまたはデザイントークンとして一度だけ定義します |
| ディスプレイ見出しと情報量の多いデータテーブルに同じスケールを使用する | 1つの比率で、この両極端にうまく対応することはほとんどありません | データにはより狭い比率(1.125)、マーケティング用途にはより広い比率(1.25~1.333)を使用します |
| 本文に文字間隔を追加する | 文字がばらけて、読む速度が遅くなります | 本文のトラッキングは0に保ち、余白が必要な場合も、大文字ラベルへの追加は最大0.04emにします |
| 暗い背景に通常の太さの白文字を使う | 光がにじんで、文字が細く弱々しく見えます | 明るい文字を暗い背景に配置する場合は、太さを1段階(ミディアム/セミボールド)上げます |
| UI のデフォルトフォントに等幅フォントを使用する、または等幅フォントと大文字を組み合わせる | ざっと読み取りにくく、「スタイルが設定されていない」ように見えます | 等幅フォントはコード、ID、数値データにのみ使用します |
隣り合う小さなサイズを、それぞれ独立したclamp()値で設定する | MIN/MAXの両端が適切でも、ビューポートの中間で曲線が近づいたり交差したりすることがあります | 隣り合う小さいサイズやラベルのサイズは固定し、clamp()はスケールの上位にのみ使用します |