結論
プロは「数字が揃わない」を CSS の font-variant-numeric: tabular-nums(OpenType の tnum)で解く。全桁を同一 advance width にして列の縦揃えとインプレース更新のレイアウトシフトを同時に潰すのが中核だ。揃え方は「数値は右揃え/小数桁が不揃いなら小数点揃え、中央揃えは禁止」、価格は通貨記号も含めて等幅化し、階層はサイズ+色で作る——monospace への逃げと擬似上付きが安っぽさの典型である。
01 — 等幅数字は font-variant-numeric で指定する
既定の数字(proportional, pnum)は桁ごとに字幅が違う。1 は細く 0 は太いため、テーブルやカウンタで列がガタつく。高レベルプロパティ font-variant-numeric: tabular-nums が OpenType tnum にマップし、全桁を同一字幅に揃える。font-feature-settings: "tnum" 1 でも同じトグルだが、同一要素の他の OpenType 機能を上書き(clobber)してしまうので非推奨。Inter / Roboto / SF / Lato / Open Sans は tnum 対応。
| 項目 | 金額 |
|---|---|
| 小計 | 1,118 |
| 送料 | 990 |
| 合計 | 12,408 |
| 項目 | 金額 |
|---|---|
| 小計 | 1,118 |
| 送料 | 990 |
| 合計 | 12,408 |
primaryfont-variant-numeric — MDN Web Docs
blogTabular Numbers in CSS — Authon Blog
02 — カウンタ/タイマーのガタつきは tnum で止める(monospace に逃げない)
ストップウォッチやカウントアップは値が更新されるたび桁の字幅差で横にジッタする。これを「揃わないから」と全体を monospace / コードフォントに差し替えるのは過剰な逃げ——質感が丸ごとコード風に変わり、字幅も無駄に広い。既存フォントのまま font-variant-numeric: tabular-nums をかければ、字幅は固定され見た目はそのままだ。
blogTabular numbers — Sebastian De Deyne
03 — 数値は右揃え、テキストは左揃え。中央揃えは禁止
数値は右から(一の位→十の位→百の位)読んで比較するため、右揃えだと桁が縦に並んで比較が一瞬で済む。中央揃えは ragged edge(ギザギザの端)を生み、桁ぞろえを破壊してスキャンを阻害する。ヘッダもデータと揃え(数値ヘッダは右、テキストヘッダは左)。本文中の数字は逆に proportional(既定)のままが読みやすく、揃え目的でない箇所に tnum を撒くと窮屈になる。
| 商品 | 在庫 |
|---|---|
| A | 7 |
| B | 340 |
| C | 28 |
| 商品 | 在庫 |
|---|---|
| A | 7 |
| B | 340 |
| C | 28 |
blogDesign Better Data Tables — Matthew Ström
blogTabular numbers — Sebastian De Deyne
04 — 小数桁が不揃いなら小数点揃えにする
単位が同じでも小数桁がバラバラな列は、右揃えだと桁(magnitude)がずれて 1 と 12.75 が誤って隣り合う。小数点で揃えれば多様なデータでも桁が比較できる。CSS Text L4 の text-align: "." right は仕様にあるが2024時点で実装ブラウザは皆無。aria-hidden のダミー span に不可視の小数を足し、visibility:hidden(display:none は不可、幅を保持できない)で物理的に桁を揃える。スクリーンリーダは実数だけ読む。
blogCharacter-based alignment — CSSence.com
secondaryWeb Typography: Designing Tables to be Read — A List Apart
05 — 価格の通貨記号も等幅にし、階層はサイズ+色で作る
価格を揃えるには数字を lining-nums tabular-nums にするだけでなく、通貨記号も等幅でないと揃いが崩れる。記号は cap height 基準で lining 数字と並ぶよう設計されている。階層は「ウェイトを軽くする」ではなくサイズ+色で作るのが正解——記号のストローク太さは数字のウェイトに合わせ、セントは小さいサイズ+同系色相の低彩度色(灰色にしない)で弱める。通貨記号をエディタの上付きボタンで縮小する擬似 superscript は、人工的に縮小された lining 記号が細く軽く見えて安っぽい。
primaryCharacter design standards: Figures — Microsoft Typography
secondaryManual: Currency Symbols — type.today
blogBook summary: Refactoring UI — sglavoie.com
06 — 通貨フォーマットはロケール駆動、フィールド幅は全変種に合わせる
記号位置・区切り・小数桁数はロケール固有だ。US は $10.20、仏は 10,00 $ USD(カンマ小数・右記号)、日本/韓国は ¥10,000(小数無)、一部中東通貨は小数3桁。フィールド幅はこの全変種に合わせて設計する。表記規約も押さえる——4桁以上はカンマ、大きな額は K/M/B で略す、負は記号の前にマイナス(-$25)、機密数字は1文字1ドットでマスク(●●●●1234)。すべて tabular-nums で等幅化して列を揃える。
blogThe UX of Currency Display — Workday Design
secondaryNumbers — Intuit Content Design
実装スニペット
/* テーブル数値列: 等幅 + 右揃え */
.num-cell {
font-variant-numeric: lining-nums tabular-nums;
text-align: right;
font-feature-settings: normal; /* clobber回避: tnumを直接書かない */
}
/* レガシー(古いブラウザ)フォールバック */
@supports not (font-variant-numeric: tabular-nums) {
.num-cell { font-feature-settings: "lnum", "tnum"; }
}
/* アニメカウンタ/タイマーのガタつき防止 */
.counter, .timer {
font-variant-numeric: tabular-nums;
/* monospaceフォントに替えない: 既存フォントのまま等幅化 */
}
/* 小数点揃え(text-align decimal 未実装の疑似実装) */
td {
font-variant-numeric: lining-nums tabular-nums;
text-align: right;
}
td [aria-hidden] { visibility: hidden; } /* display:none不可・幅を保持 */
/* HTML: 整数値に不可視の小数ダミーを足して桁を揃える
<td>1<span aria-hidden="true">.00</span></td>
<td>12<span aria-hidden="true">.75</span></td> */
/* 価格の階層(サイズ+色、通貨記号も等幅) */
.price {
font-variant-numeric: lining-nums tabular-nums; /* 記号も含め等幅 */
display: inline-flex;
align-items: baseline;
}
.price__symbol { font-size: 0.7em; } /* 上付きボタンでなくサイズ調整 */
.price__cents {
font-size: 0.6em;
color: hsl(220 30% 55%); /* 同系色相・低彩度で弱める(灰色にしない) */
}
/* HTML: $1,234.56 / 末尾ゼロは通貨では保持
<span class="price"><span class="price__symbol">$</span>1,234<span class="price__cents">.56</span></span> */
チェックリスト
- テーブル列・価格・タイマー・カウンタに
font-variant-numeric: tabular-numsを指定したか - 本文中の数字には
tnumを撒かず proportional(既定)のままにしたか font-feature-settings: "tnum" 1を避け、高レベルプロパティを使ったか- 数値列は右揃え、テキスト列は左揃え、中央揃えを使っていないか
- ヘッダもデータと揃えたか(数値ヘッダ右/テキストヘッダ左)
- 小数桁が不揃いな列は小数点揃え(aria-hidden ダミー span)にしたか
- 価格の通貨記号も等幅化し、擬似上付きで縮小していないか
- 価格の階層をサイズ+色で作り、記号の太さを数字のウェイトに合わせたか
- カンマ区切り・負号の位置・ロケール別小数桁を全変種のフィールド幅で吸収したか
- 採用フォントが実機で
tnum/lnumグリフを持つか確認したか
限界 / 出典
tnum/lnum グリフが無ければ効かない。Inter / Roboto / SF / Lato / Open Sans 等は対応するが、採用フォントの数字機能を実機で確認すること。小数点揃えのネイティブ構文 text-align: "." right は2024時点で実装ブラウザ皆無で、aria-hidden ダミー span はあくまで疑似実装——生成/編集ワークフローに不可視 span 混入の手間が残る。価格の記号:数字のサイズ比(0.7em/0.6em)は一般的な出発値で、フォントごとに目視調整が必要。ロケール別フォーマットは代表例であり、個別通貨は別途検証推奨。色での弱め方など一部原則は単一ブログ由来。primaryfont-variant-numeric — MDN Web Docs
blogTabular numbers — Sebastian De Deyne
blogTabular Numbers in CSS — font-variant-numeric vs monospace hacks — Authon Blog
blogDesign Better Data Tables — Matthew Ström (Mission Log)
secondaryWeb Typography: Designing Tables to be Read, Not Looked At — A List Apart
blogCharacter-based alignment — CSSence.com
secondaryBest Practices in Table Design — Science Editor
primaryCharacter design standards: Figures for Latin 1 — Microsoft Typography
secondaryManual: Currency Symbols — type.today
blogBook summary: Refactoring UI — sglavoie.com
blogThe UX of Currency Display — What's in a $ Sign? — Workday Design
secondaryNumbers — Intuit Content Design