結論
プロは表を「飾る」のではなく、ノイズを引くことで読みやすくする。文字は左揃え・数値は右揃え+等幅数字(tabular-nums)で桁を縦に揃え、罫線は1pxの極薄グレーかゼブラのどちらか一方だけ、行高は40/48/56pxの3段密度・セル左右16px(列間32px)を守る。Material Designのトークン(行52px/ヘッダ56px、罫線on-surface 12%、hover 4%)を信頼できるベースラインにすれば、ほとんどの表は「装飾を増やさず」読みやすくなる。
01 — 数値は右揃え+tabular-nums、文字は左揃え
最も安っぽく見える原因は数値の中央揃え・左揃えだ。数字は一の位から右→左へ桁を比較するので右揃えが原則。文字は左→右に読み辞書順で比べるので左揃え。中央揃えは行頭・行末がギザギザ(ragged)になり視線が左右に飛ぶため、チェックボックスや星アイコンだけに限定する。ヘッダの揃えも列データに追従させると縦のエッジが揃う。
| 1,250 |
| 98 |
| 14,008 |
| 307 |
| 1,250 |
| 98 |
| 14,008 |
| 307 |
blogDesign Better Data Tables — Matthew Ström (Mission Log)
02 — 等幅数字(tabular-nums)で桁を縦に揃える
右揃えにしても、プロポーショナル数字のままだと「1」と「8」で字幅が違い、桁が縦に揃わずガタつく。font-variant-numeric: tabular-nums lining-nums(古い環境用にfont-feature-settings:"tnum" 1,"lnum" 1)で全数字を等幅化すると、列がきれいな縦のグリッドになる。SF Pro/Work Sansは真のtabular figuresを持つ。なければmonospaceがフォールバック。
| 1,111 |
| 8,888 |
| 1,818 |
| 10,945 |
| 1,111 |
| 8,888 |
| 1,818 |
| 10,945 |
blogDesign Better Data Tables — Matthew Ström (Mission Log)
03 — 罫線かゼブラ、どちらか一方に絞る
縦横フル罫線の格子は、データより罫線が目立ち1990年代のスプレッドシート印象になる。構造は余白と整列で作り、罫線は1px極薄グレー(Material基準 on-surface 12%)の横線のみ・必要箇所だけ。ゼブラを使うなら罫線は外す——交互の塗りが行区切りの役割を果たすので併用は冗長でノイズになる。
| 商品 | 在庫 |
|---|---|
| USB-Cケーブル | 120 |
| 充電器 | 45 |
| モバイルバッテリー | 8 |
| 商品 | 在庫 |
|---|---|
| USB-Cケーブル | 120 |
| 充電器 | 45 |
| モバイルバッテリー | 8 |
blog9 Design Techniques for User-Friendly Tables — UX Movement
04 — ゼブラは「1色・1行ごと・極薄4%」が最安全解
行の取り違えを防ぐゼブラだが、濃い色で塗ると縞模様自体がノイズになる。正解は on-surface 約4% opacity の極薄グレーで、1行交互の単色。A List Apartの実証(n=2,276)では単色1行ゼブラが8問中3問で素のテーブルより正答率が有意に高く、残りも有意差なし=悪化させない安全策。迷ったら密で長い表のデフォルトにする。
| 東京 | 1,250 |
| 大阪 | 980 |
| 名古屋 | 640 |
| 福岡 | 410 |
| 東京 | 1,250 |
| 大阪 | 980 |
| 名古屋 | 640 |
| 福岡 | 410 |
primaryZebra Striping: More Data for the Case — A List Apart
05 — 行を詰めすぎない(40/48/56pxの3段密度)
密度を上げすぎる(30px以下)とパースエラーが増え、かえって読みにくくなる。行高は Condensed 40px / Regular 48px / Relaxed 56px の名前付き3モードを基本に、セル左右パディングは最低16px(列間32px)。Materialの基準は行52px・ヘッダ56px。読み物用途ならRegular 48px固定で十分だ。
| 注文 #1042 | ¥3,200 |
| 注文 #1043 | ¥980 |
| 注文 #1044 | ¥12,400 |
| 注文 #1045 | ¥540 |
| 注文 #1042 | ¥3,200 |
| 注文 #1043 | ¥980 |
blogData Table Design UX Patterns & Best Practices — Pencil & Paper
06 — ヘッダは sticky で固定する
縦スクロールで列ラベル(=文脈)が消えると、どの列が何の数値か分からなくなる。position:sticky; top:0 でヘッダを固定すれば、スクロール中もラベルが残る。注意点は背景——sticky要素は不透明背景(#fffなど)にしないと下の行が透けて破綻する。下のデモは両方ともスクロールできる。
| 日付 | 売上 |
|---|---|
| 06/14 | 1,200 |
| 06/15 | 980 |
| 06/16 | 1,540 |
| 06/17 | 760 |
| 06/18 | 2,010 |
| 06/19 | 1,330 |
| 06/20 | 890 |
| 日付 | 売上 |
|---|---|
| 06/14 | 1,200 |
| 06/15 | 980 |
| 06/16 | 1,540 |
| 06/17 | 760 |
| 06/18 | 2,010 |
| 06/19 | 1,330 |
| 06/20 | 890 |
blogData Table Design UX Patterns & Best Practices — Pencil & Paper
実装スニペット
読みやすいベーステーブル。罫線は横線のみ・極薄、文字左揃え・数値右揃え+tabular-nums。
table {
width: 100%;
border-collapse: collapse;
font-feature-settings: "palt"; /* 日本語の約物詰め */
}
th, td {
padding: 14px 16px; /* 縦14 / 左右16(列間32) */
text-align: left; /* 文字は左揃え */
vertical-align: middle;
border-bottom: 1px solid rgba(0,0,0,.12); /* Material: on-surface 12% */
color: rgba(0,0,0,.87); /* 本文 on-surface 87% */
}
thead th {
height: 56px; /* ヘッダはボディ+4px */
font-weight: 600;
color: rgba(0,0,0,.6);
border-bottom: 2px solid rgba(0,0,0,.12);
}
tbody tr { height: 52px; } /* Material 基準行高 */
/* 数値列: 右揃え+等幅数字 */
.num, td.num, th.num {
text-align: right;
font-variant-numeric: tabular-nums lining-nums;
font-feature-settings: "tnum" 1, "lnum" 1; /* 古い環境のフォールバック */
}
ゼブラを使うなら横罫線は消す(冗長回避)。塗りは4% opacityまで。
tbody tr:nth-child(even) { background: rgba(0,0,0,.04); } /* on-surface 4% */
tbody tr:nth-child(even) td,
tbody tr:nth-child(odd) td { border-bottom: none; }
/* hover / 選択も極薄に */
tbody tr:hover { background: rgba(0,0,0,.04); }
tbody tr[aria-selected="true"] { background: rgba(25,118,210,.04); } /* primary 4% */
sticky ヘッダ+左端列固定。固定要素は必ず不透明背景に。
.table-scroll { overflow: auto; max-height: 70vh; }
thead th {
position: sticky;
top: 0;
z-index: 2;
background: #fff; /* 透けないよう不透明背景必須 */
}
/* 左端の識別子列を横スクロールで固定 */
th:first-child, td:first-child {
position: sticky;
left: 0;
background: #fff;
z-index: 1;
}
thead th:first-child { z-index: 3; } /* 角は最前面 */
密度3モード+レスポンシブ。data-density属性で切り替える。
:root { --row-h: 48px; --cell-py: 12px; --cell-px: 16px; } /* Regular */
[data-density="condensed"] { --row-h: 40px; --cell-py: 8px; }
[data-density="relaxed"] { --row-h: 56px; --cell-py: 22px; }
tbody tr { height: var(--row-h); }
th, td { padding: var(--cell-py) var(--cell-px); }
/* タッチ操作対象は密度に関係なく48px確保 */
td .action, td input[type="checkbox"] { min-height: 48px; min-width: 48px; }
@media (max-width: 1080px) {
:root { --cell-py: 8px; --cell-px: 10px; } /* モバイルは詰める */
}
チェックリスト
- 文字セルは左揃え、数値セルは右揃えになっているか(中央揃えはチェックボックス・星・アイコンのみ)
- 数値列に
font-variant-numeric: tabular-nums lining-numsを指定し、桁が縦に揃っているか - ヘッダの揃えを列データに追従させたか(数値列のヘッダは右揃え)
- 罫線かゼブラのどちらか一方に絞ったか(両方併用していないか)
- 罫線は1px・極薄グレー(on-surface 12%相当)の横線のみで、縦の格子を引いていないか
- ゼブラは単色・1行交互・4% opacityの極薄に抑えたか
- 行高は40/48/56pxのいずれか、セル左右パディングは最低16px(列間32px)あるか
- 長い表でヘッダを
position:sticky固定し、その背景を不透明にしたか - 同一列内で小数桁・桁区切り・通貨表記を統一したか
- タッチUIなら操作対象(チェックボックス等)が48px以上あるか
限界 / 出典
font-variant-numeric はフォントがtabular figuresを持つ場合のみ有効。 (7) 触り対象48pxはタッチUI限定で、ポインタ専用の業務画面では緩めてよい。primarymaterial-components-web mdc-data-table _data-table-theme.scss
primaryData tables — Material Design (m2)
primaryZebra Striping: More Data for the Case — A List Apart
blogDesign Better Data Tables — Matthew Ström (Mission Log)
blogData Table Design UX Patterns & Best Practices — Pencil & Paper
blogThe Ultimate Guide to Designing Data Tables — UI Prep
blog9 Design Techniques for User-Friendly Tables — UX Movement
blogData table UI design reference guide for 2026 — Setproduct