タイポグラフィトークンパターン
問題
Tailwind CSS はデフォルトで13のフォントサイズステップ(text-xs から text-9xl まで)、9つの font-weight 値(font-thin から font-black まで)、6つ以上の line-height 値、複数の font-family オプションを提供しています。チームは本文テキストに text-sm、text-base、text-lg を交互に使い、あるコンポーネントでは font-semibold を使い、別のコンポーネントでは同じ視覚的な強調のために font-bold を使うことになります。
このタイポグラフィのずれは、スペーシングやカラーのずれよりも見つけにくいものです。違いが微妙だからです — 14px vs 16px の本文テキスト、font-medium vs font-semibold など — しかし、誰も正確に指摘できないまま不一致な印象を与えるインターフェースへと蓄積されていきます。
解決方法
すべてのデフォルトタイポグラフィトークンをリセットし、抽象的なサイズ名を使った小さなセットを定義します:
- フォントサイズ:6サイズ —
xs、sm、base、lg、xl、2xl - フォントウェイト:3ウェイト —
normal、medium、bold - 行の高さ:3値 —
tight、normal、relaxed - フォントファミリー:2ファミリー —
sans、mono
なぜセマンティック名ではなく抽象名なのか
トークンをタイポグラフィ上の役割で命名するのは自然な発想です — caption、body、subheading、heading、display。最初はすっきりして見えますが、トークン名が用途のコンテキストをハードコードしてしまうという問題があります。
例えば、subheading トークンが 20px だとします。商品価格、ナビゲーションリンク、インフォコールアウトにも 20px のテキストが必要になりました。これらはどれもサブヘディングではありません。2つの悪い選択肢が残ります:
- サブヘディングでないものに
text-subheadingを使う — 誤解を招き、他の開発者を混乱させます - 別の名前で新しい 20px トークンを作る — トークンが肥大化し、同じ値が重複します
lg のような抽象名ならこの問題を解決できます。20px テキストが必要な要素はすべて text-lg を使います。役割はトークン名ではなくコンテキストから決まります。
これは Three-Tier Color Strategy や Three-Tier Font-Size Strategy と同じ考え方です。コアレイヤーでは中立的で再利用可能な名前を使います。heading や caption のようなセマンティック名はテーマレイヤーに属します — CSS カスタムプロパティやコンポーネントレベルのトークンとして、コアサイズを参照する形で定義します:
/* Core layer (@theme) — abstract, reusable scale */
--font-size-lg: 1.25rem;
/* Theme layer (project CSS) — semantic aliases */
:root {
--font-subheading: var(--font-size-lg);
}
@theme タイポグラフィブロック
アプローチB(デフォルトテーマなしの個別インポート)を使う場合、リセット行は不要です — トークンを直接定義するだけです。アプローチA(@import "tailwindcss")を使う場合は、以下のコメント内のリセット行を追加してください。
@theme {
/* If using Approach A (@import "tailwindcss"), uncomment these resets:
--font-size-*: initial;
--font-weight-*: initial;
--line-height-*: initial;
--font-family-*: initial;
--letter-spacing-*: initial;
*/
/* ── Font sizes with paired line-heights (6 steps) ── */
--font-size-xs: 0.75rem; /* 12px */
--font-size-xs--line-height: 1.5;
--font-size-sm: 0.875rem; /* 14px */
--font-size-sm--line-height: 1.5;
--font-size-base: 1rem; /* 16px */
--font-size-base--line-height: 1.75;
--font-size-lg: 1.25rem; /* 20px */
--font-size-lg--line-height: 1.5;
--font-size-xl: 1.75rem; /* 28px */
--font-size-xl--line-height: 1.25;
--font-size-2xl: 2.5rem; /* 40px */
--font-size-2xl--line-height: 1.25;
/* ── Font weights (3 steps) ── */
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-bold: 700;
/* ── Line heights (3 steps — for manual overrides) ── */
--line-height-tight: 1.25;
--line-height-normal: 1.5;
--line-height-relaxed: 1.75;
/* ── Font families (2 families) ── */
--font-family-sans: "Inter", system-ui, sans-serif;
--font-family-mono: "JetBrains Mono", ui-monospace, monospace;
}
各フォントサイズは --font-size-*--line-height の規約を使って最適な line-height とペアリングされています。text-base と書くだけで font-size: 1rem と line-height: 1.75 の両方が設定されます — 別途 leading-* クラスを指定する必要はありません。スタンドアロンの line-height トークンは、ペアリングされた値が合わない場合の手動オーバーライド用に残してあります。
この設定後:
text-sm— 動作する(font-size: 0.875rem; line-height: 1.5に解決される)text-3xl— ビルドエラー(--font-size-3xlトークンが存在しない)font-semibold— ビルドエラー(--font-weight-semiboldトークンが存在しない)font-bold— 動作する(font-weight: 700に解決される)leading-normal— 動作する(line-height: 1.5に解決される)
デモ
デフォルトフォントサイズ vs 抽象タイポグラフィトークン
左のカラムは Tailwind の13のデフォルトフォントサイズステップ — text-xs から text-9xl までを示しています。右のカラムはそれらを置き換える6つの抽象サイズです。各トークンはスケール内のステップであり、特定の UI 上の役割には紐づいていません。
タイポグラフィスケールカード
6つの抽象サイズすべてとペアリングされた line-height を示す視覚的な階層カードです。これがプロジェクトの完全なタイポグラフィ語彙であり、どのコンテキストでも再利用できます。
同じサイズ、異なる役割
抽象名の最大の利点は、text-lg がカードタイトル、価格表示、ナビゲーションリンクのどれにも同じように使えることです。subheading のようなセマンティック名では、同じ 20px の値に対して3つの別々のトークンが必要になります。
抽象タイポグラフィトークンを使った記事レイアウト
6つの抽象フォントサイズ、3つのウェイト、3つの line-height のみを使った完全な記事レイアウトです。text-lg がサブタイトルとセクション見出しの両方に再利用されていることに注目してください — 同じサイズ、異なる役割です。セマンティック命名では、同じ値に対して別々の subtitle トークンと section-heading トークンが必要になります。
使い分け
タイポグラフィトークンは、カラートークンや親記事のスペーシング戦略と自然に組み合わさります。これらを合わせることで、視覚的なずれの最も一般的な3つの原因を制約するタイトなデザイントークンシステムの核を形成します。
タイポグラフィトークンを適用すべきケース:
- プロジェクトで実際に3つ以上のフォントサイズが使われている場合 — ちょうど6つに制約しましょう
- 複数の開発者がマークアップを書き、それぞれが異なるテキストサイズを使っている場合
- どのコンテキストでも再利用できるフォントサイズトークンが必要な場合 — 特定のコンポーネントの役割に紐づけないトークンが求められるケース
関連記事
- Three-Tier Font-Size Strategy — これらのトークン選択の背景にある完全な概念的アーキテクチャ(スケール → テーマ → コンポーネント)
- Three-Tier Color Strategy — 同じ三層アーキテクチャをカラーに適用したもの
- Color Token Patterns — 同じタイトトークンアプローチを使ったセマンティックカラースケール