CSSで、表の数字の幅をそろえて読みやすくする方法
表の数字の桁を縦にそろえるには、CSS の font-variant-numeric: tabular-nums で数字をすべて同じ幅にし、数字の列を text-align: right で右寄せにします。この2つがそろうと、一の位、十の位、カンマの位置がどの行でも同じ場所に来ます。
検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。フォントは Inter 4.0、Noto Sans CJK JP、DejaVu Sans を使い、検証用のページを Playwright で開いて、文字ごとの位置と幅を測りました。Firefox と Safari、Windows や macOS に入っているフォントでの表示は試していません。各ブラウザの対応バージョンは、互換性データ(@mdn/browser-compat-data 8.1.8)の値です。

書き方
数字の列のセルに num というクラスを付け、表全体に tabular-nums を指定します。
<table>
<thead>
<tr><th>月</th><th class="num">売上(円)</th><th class="num">伸び率(%)</th></tr>
</thead>
<tbody>
<tr><td>4月</td><td class="num">111,111</td><td class="num">8.50</td></tr>
<tr><td>5月</td><td class="num">888,888</td><td class="num">12.25</td></tr>
<tr><td>6月</td><td class="num">47,210</td><td class="num">3.00</td></tr>
<tr><td>7月</td><td class="num">1,019</td><td class="num">10.75</td></tr>
</tbody>
</table>
table {
font-variant-numeric: tabular-nums;
}
.num {
text-align: right;
}
font-variant-numeric は子要素に継承されます(CSS Fonts Level 4 の仕様)。検証環境でも、table に指定すると、中の td の値は tabular-nums になりました。表ごとに1回書けば足ります。見出しの th にも num を付けておくと、上の画像のように、列の見出しも数字と同じ右側にそろいます。
数字の幅がそろっていないと、右寄せでも桁がずれる
欧文フォントには、数字ごとに幅が違うものがあります。検証環境で、Inter の数字1文字ずつの幅を測ると、次のようになりました。単位は em(文字の大きさに対する割合)です。
| 数字 | 指定なし | tabular-nums |
|---|---|---|
| 0 | 0.631 | 0.648 |
| 1 | 0.407 | 0.648 |
| 4 | 0.646 | 0.648 |
| 7 | 0.566 | 0.648 |
| 8 | 0.619 | 0.648 |
指定がないと、「1」は「4」より 0.24em ほど細くなります。tabular-nums を指定すると、0〜9 のすべてが 0.648em になりました。MDN の font-variant-numeric の説明では、tabular-nums は数字を同じ大きさ(幅)で表示して表の中でそろえやすくする指定で、OpenType の tnum の機能に対応するとされています。
この幅の違いは、右寄せにしても消えません。検証環境で、20px の Inter で 111,111、888,888、47,210、1,019 を右寄せにして、右から数えて同じ位置にある文字(一の位、十の位…)の右端が、行どうしでどれだけずれるかを測りました。
| 右から数えた文字 | 指定なし | tabular-nums |
|---|---|---|
| 1文字目(一の位) | 0.00px | 0.00px |
| 2文字目(十の位) | 4.48px | 0.00px |
| 4文字目(カンマ) | 12.72px | 0.00px |
| 7文字目(十万の位) | 22.03px | 0.00px |
右寄せなので一の位の右端はそろいますが、左の桁ほどずれが大きくなります。1 だけの 111,111 と、8 だけの 888,888 では、文字列全体の幅が 52.84px と 79.11px で、26px あまり違いました。tabular-nums を指定すると、どちらも 83.19px になり、すべての桁でずれが 0 になりました。
左寄せのままだと、幅をそろえても桁はそろわない
tabular-nums を指定しても、セルが左寄せのままだと桁はそろいません。表のセル(td)の text-align の初期値は start で、左から右に書くページでは左寄せになります。
検証環境で、tabular-nums だけを指定し、text-align を指定しないセルに 111,111、47,210、1,019 を入れると、text-align の値は start のままで、一の位の右端の位置は 94.19px、81.22px、68.25px でした。1桁少ないごとに、数字1文字分(12.97px)ずつ左にずれています。数字の幅がそろっていても、桁数の違う数字は、右端を合わせないと桁が並びません。
小数は、小数点以下の桁数をそろえる
小数を含む列では、右寄せと tabular-nums だけでは小数点の位置がそろいません。検証環境で、12.5、3.25、100、0.8 を並べると、小数点の左端は、12.5 と 0.8 では 36.94px、3.25 では 23.97px で、100 には小数点がありません。
小数点以下の桁数を、表示する前に同じにしておくと、小数点が1つの縦の線に並びます。JavaScript で値を作るなら、Intl.NumberFormat の minimumFractionDigits と maximumFractionDigits を同じにします。
const format = new Intl.NumberFormat('ja-JP', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
['12.5', '3.25', '100', '0.8'].map((v) => format.format(Number(v)));
// → 12.50, 3.25, 100.00, 0.80
検証環境で、この 12.50、3.25、100.00、0.80 を表示すると、小数点の左端は4行とも 49.91px にそろいました。
CSS Text Level 4 の仕様には、text-align: "." のように文字を指定して、その文字の位置で列をそろえる書き方があります。ただし、検証環境の Chromium 153 では CSS.supports('text-align', '"."') が false で、使えませんでした。互換性データの text-align の値にも、この書き方は入っていません。
もともと数字の幅がそろっているフォントもある
数字が最初から同じ幅で作られているフォントでは、tabular-nums を指定しても見た目は変わりません。検証環境では、Noto Sans CJK JP の数字はすべて 0.555em、DejaVu Sans の数字はすべて 0.636em で、指定の有無で幅は同じでした。
あとで表のフォントを Inter のような数字の幅が違うフォントに変えても、指定が残っていれば桁はそろったままです。
font-feature-settings でも同じ結果になる
フォントの tnum の機能を直接オンにする font-feature-settings: "tnum" でも、検証環境では tabular-nums と同じ幅(83.19px)になり、桁のずれも 0 でした。
ただ、MDN の font-feature-settings の説明では、できる限り font-variant-numeric などの個別のプロパティを使うべきだとされています。数字の幅をそろえるだけなら、font-variant-numeric: tabular-nums を使います。
主要なブラウザで使える
互換性データでは、font-variant-numeric の tabular-nums は、Chrome 52、Edge 79、Firefox 34、Safari 9.1、iOS の Safari 9.3、Android の Chrome 52 から使えます。





