テーブル デザイン見本
HTML の <table> 要素と CSS を組み合わせた表スタイルの実装デモ。ボタンで見た目の違いをリアルタイムで確認しながら、コピーしてすぐに使えるコードを掲載しています。
HTML・CSS・JSコードプレビューツール にて実装確認ができます。
① border-collapse — セルのボーダーを結合・分離する
| 月 | 売上 | 経費 | 利益 |
|---|---|---|---|
| 4月 | 50,000 | 40,000 | 10,000 |
| 5月 | 80,000 | 65,000 | 15,000 |
| 6月 | 40,000 | 32,000 | 8,000 |
| 7月 | 60,000 | 45,000 | 15,000 |
現在: border-collapse: collapse
<table>
<thead>
<tr>
<th>月</th>
<th>売上</th>
<th>経費</th>
<th>利益</th>
</tr>
</thead>
<tbody>
<tr><td>4月</td><td>50,000</td><td>40,000</td><td>10,000</td></tr>
<tr><td>5月</td><td>80,000</td><td>65,000</td><td>15,000</td></tr>
<tr><td>6月</td><td>40,000</td><td>32,000</td><td>8,000</td></tr>
<tr><td>7月</td><td>60,000</td><td>45,000</td><td>15,000</td></tr>
</tbody>
</table>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #64748b;
padding: 8px 14px;
text-align: center;
}
デフォルト値は separate(各セルのボーダーが独立して描画されるため二重線になる)。collapse を指定すると隣り合うセルのボーダーが1本に統合され、すっきりした表になります。実務ではほぼすべてのケースで collapse を使うのが一般的です。
② ヘッダースタイル — 罫線 / 太い区切り / カラーヘッダー
| 月 | 売上 | 経費 | 利益 |
|---|---|---|---|
| 4月 | 50,000 | 40,000 | 10,000 |
| 5月 | 80,000 | 65,000 | 15,000 |
| 6月 | 40,000 | 32,000 | 8,000 |
| 7月 | 60,000 | 45,000 | 15,000 |
現在: 罫線のみ
<table>
<thead>
<tr>
<th>月</th>
<th>売上</th>
<th>経費</th>
<th>利益</th>
</tr>
</thead>
<tbody>
<tr><td>4月</td><td>50,000</td><td>40,000</td><td>10,000</td></tr>
<tr><td>5月</td><td>80,000</td><td>65,000</td><td>15,000</td></tr>
<tr><td>6月</td><td>40,000</td><td>32,000</td><td>8,000</td></tr>
<tr><td>7月</td><td>60,000</td><td>45,000</td><td>15,000</td></tr>
</tbody>
</table>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #475569;
padding: 8px 14px;
text-align: center;
}
<thead> と <tbody> を使い分けると、CSS でヘッダー行だけにスタイルを当てやすくなります。「太い区切り線」は thead に border-bottom を指定するだけでヘッダーと本文の境界を強調でき、スタイリッシュな表が簡単に作れます。
③ ストライプ — :nth-child で交互に背景色を付ける
| 月 | 売上 | 経費 | 利益 |
|---|---|---|---|
| 4月 | 50,000 | 40,000 | 10,000 |
| 5月 | 80,000 | 65,000 | 15,000 |
| 6月 | 40,000 | 32,000 | 8,000 |
| 7月 | 60,000 | 45,000 | 15,000 |
現在: 奇数行 (odd) に背景色
<table>
<thead>
<tr>
<th>月</th>
<th>売上</th>
<th>経費</th>
<th>利益</th>
</tr>
</thead>
<tbody>
<tr><td>4月</td><td>50,000</td><td>40,000</td><td>10,000</td></tr>
<tr><td>5月</td><td>80,000</td><td>65,000</td><td>15,000</td></tr>
<tr><td>6月</td><td>40,000</td><td>32,000</td><td>8,000</td></tr>
<tr><td>7月</td><td>60,000</td><td>45,000</td><td>15,000</td></tr>
</tbody>
</table>
table {
border-collapse: collapse;
width: 100%;
}
thead th {
background-color: #1e293b;
color: #fff;
padding: 8px 14px;
text-align: center;
}
tbody td {
padding: 8px 14px;
text-align: center;
}
tbody tr:nth-child(odd) {
background-color: #dbeafe;
}
tbody の tr に :nth-child(odd) を指定すると奇数行(1・3・5…行目)に、even を指定すると偶数行に背景色が付きます。行数が多い表では縞模様にするだけで視認性が大幅に上がります。thead の th には別途スタイルを設定することでヘッダー行と本文を明確に区別できます。
④ ヘッダーなしテーブル — <tbody> のみで構成する
| 4月 | 50,000 | 40,000 | 10,000 |
| 5月 | 80,000 | 65,000 | 15,000 |
| 6月 | 40,000 | 32,000 | 8,000 |
| 7月 | 60,000 | 45,000 | 15,000 |
現在: 罫線スタイル
<table>
<tbody>
<tr><td>4月</td><td>50,000</td><td>40,000</td><td>10,000</td></tr>
<tr><td>5月</td><td>80,000</td><td>65,000</td><td>15,000</td></tr>
<tr><td>6月</td><td>40,000</td><td>32,000</td><td>8,000</td></tr>
<tr><td>7月</td><td>60,000</td><td>45,000</td><td>15,000</td></tr>
</tbody>
</table>
table {
border-collapse: collapse;
width: 100%;
}
td {
border: 1px solid #475569;
padding: 8px 14px;
text-align: center;
}
<thead> を省いて <tbody> だけにすると、すべての行が同じスタイルになるシンプルなヘッダーなし表を作れます。CSS のスタイルは th ではなく td のみに指定します。名簿・住所録など、全行が同じ種類のデータを並べる場合に向いています。
⑤ レスポンシブ対応 — overflow-x: auto でスマホに対応
| 月 | 売上(円) | 経費(円) | 利益(円) | 前月比 | 備考 |
|---|---|---|---|---|---|
| 4月 | 50,000 | 40,000 | 10,000 | — | 開始月 |
| 5月 | 80,000 | 65,000 | 15,000 | +50% | 好調 |
| 6月 | 40,000 | 32,000 | 8,000 | -47% | 低調 |
| 7月 | 60,000 | 45,000 | 15,000 | +88% | 回復 |
現在: overflow-x: auto(横スクロール可能)
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>月</th>
<th>売上(円)</th>
<th>経費(円)</th>
<th>利益(円)</th>
<th>前月比</th>
<th>備考</th>
</tr>
</thead>
<tbody>
<tr><td>4月</td><td>50,000</td><td>40,000</td><td>10,000</td><td>—</td><td>開始月</td></tr>
<tr><td>5月</td><td>80,000</td><td>65,000</td><td>15,000</td><td>+50%</td><td>好調</td></tr>
<tr><td>6月</td><td>40,000</td><td>32,000</td><td>8,000</td><td>-47%</td><td>低調</td></tr>
<tr><td>7月</td><td>60,000</td><td>45,000</td><td>15,000</td><td>+88%</td><td>回復</td></tr>
</tbody>
</table>
</div>
.table-wrapper {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
table {
border-collapse: collapse;
white-space: nowrap;
}
th {
background-color: #2563eb;
color: #fff;
padding: 8px 14px;
text-align: center;
}
td {
border: 1px solid #cbd5e1;
padding: 8px 14px;
text-align: center;
}
列数が多い表はスマホ幅で崩れがちです。table を div でラップし、div に overflow-x: auto を指定すると、表が狭い画面でも横スクロールで閲覧できます。table 自体に white-space: nowrap を追加するとセル内でのテキスト折り返しを防ぎ、レイアウトが崩れにくくなります。
⑥ colspan / rowspan — セルを結合する
| 月 | 売上 | 経費 | 利益 |
|---|---|---|---|
| 4月 | 50,000 | 40,000 | 10,000 |
| 5月 | 80,000 | 65,000 | 15,000 |
| 6月 | 40,000 | 32,000 | 8,000 |
| 2026年 上期 売上実績 | |||
|---|---|---|---|
| 月 | 売上 | 経費 | 利益 |
| 4月 | 50,000 | 40,000 | 10,000 |
| 5月 | 80,000 | 65,000 | 15,000 |
| 6月 | 40,000 | 32,000 | 8,000 |
| 合計 | 33,000 | ||
| 四半期 | 月 | 売上 | 利益 |
|---|---|---|---|
| 第1四半期 | 4月 | 50,000 | 10,000 |
| 5月 | 80,000 | 15,000 | |
| 6月 | 40,000 | 8,000 | |
| 第2四半期 | 7月 | 60,000 | 15,000 |
| 8月 | 75,000 | 18,000 |
現在: 結合なし
<table>
<thead>
<tr><th>月</th><th>売上</th><th>経費</th><th>利益</th></tr>
</thead>
<tbody>
<tr><td>4月</td><td>50,000</td><td>40,000</td><td>10,000</td></tr>
<tr><td>5月</td><td>80,000</td><td>65,000</td><td>15,000</td></tr>
<tr><td>6月</td><td>40,000</td><td>32,000</td><td>8,000</td></tr>
</tbody>
</table>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #94a3b8;
padding: 8px 14px;
text-align: center;
}
thead th {
background-color: #1e293b;
color: #fff;
}
colspan は横方向、rowspan は縦方向にセルを結合する属性です。CSS ではなく HTML 側の属性で指定します。表の上部にタイトル行を置く、最下部に合計行を置く、左端でカテゴリをまとめる、といった実務でよくある表現がこれだけで作れます。
colspan=”3″ を指定したセルは3列分を占めるため、その行に書く td は「4個ではなく2個」になります。rowspan も同じで、結合された2行目以降では左端の td を書きません。ここを減らし忘れると、その行だけ列が1つ多くなって表が右にはみ出します。「セル結合したら表が崩れた」という失敗のほぼすべてがこれです。
⑦ caption / scope — 表にタイトルを付け、読み上げに対応する
| 月 | 売上 | 経費 | 利益 |
|---|---|---|---|
| 4月 | 50,000 | 40,000 | 10,000 |
| 5月 | 80,000 | 65,000 | 15,000 |
| 6月 | 40,000 | 32,000 | 8,000 |
現在: caption-side: top
<table>
<caption>2026年 上期 売上実績(単位:円)</caption>
<thead>
<tr>
<th scope="col">月</th>
<th scope="col">売上</th>
<th scope="col">経費</th>
<th scope="col">利益</th>
</tr>
</thead>
<tbody>
<tr><th scope="row">4月</th><td>50,000</td><td>40,000</td><td>10,000</td></tr>
<tr><th scope="row">5月</th><td>80,000</td><td>65,000</td><td>15,000</td></tr>
<tr><th scope="row">6月</th><td>40,000</td><td>32,000</td><td>8,000</td></tr>
</tbody>
</table>
table {
border-collapse: collapse;
width: 100%;
}
caption {
caption-side: top;
padding: 6px 2px 10px;
font-size: 0.88rem;
font-weight: 700;
color: #1e293b;
text-align: left;
}
thead th {
background-color: #1e293b;
color: #fff;
padding: 8px 14px;
text-align: center;
}
tbody th {
background-color: #f1f5f9;
border: 1px solid #cbd5e1;
padding: 8px 14px;
font-weight: 700;
text-align: center;
}
tbody td {
border: 1px solid #cbd5e1;
padding: 8px 14px;
text-align: center;
}
caption は table 直下の先頭に置く専用のタイトル要素です。表のすぐ上に p タグで見出しを置くのと違い、「この文章はこの表のタイトルである」という関係がブラウザと支援技術に正しく伝わります。caption-side: bottom を指定すれば、見た目だけ表の下に移動できます。
scope=”col” は「この th は縦一列の見出し」、scope=”row” は「この th は横一行の見出し」という意味です。画面で見れば一目でわかる関係も、スクリーンリーダーは推測でしか判断できません。scope があると「4月の、利益は、10,000」のようにセルと見出しを結び付けて読み上げられます。見た目は一切変わりませんが、表のアクセシビリティはこの一手間でほぼ決まります。
⑧ tr:hover — マウスを乗せた行を強調する
| 月 | 売上 | 経費 | 利益 |
|---|---|---|---|
| 4月 | 50,000 | 40,000 | 10,000 |
| 5月 | 80,000 | 65,000 | 15,000 |
| 6月 | 40,000 | 32,000 | 8,000 |
| 7月 | 60,000 | 45,000 | 15,000 |
現在: ホバー効果なし
<table>
<thead>
<tr><th>月</th><th>売上</th><th>経費</th><th>利益</th></tr>
</thead>
<tbody>
<tr><td>4月</td><td>50,000</td><td>40,000</td><td>10,000</td></tr>
<tr><td>5月</td><td>80,000</td><td>65,000</td><td>15,000</td></tr>
<tr><td>6月</td><td>40,000</td><td>32,000</td><td>8,000</td></tr>
<tr><td>7月</td><td>60,000</td><td>45,000</td><td>15,000</td></tr>
</tbody>
</table>
table {
border-collapse: collapse;
width: 100%;
}
thead th {
background-color: #1e293b;
color: #fff;
padding: 8px 14px;
text-align: center;
}
tbody td {
border-bottom: 1px solid #e2e8f0;
padding: 8px 14px;
text-align: center;
}
tbody tr {
transition: background-color 0.15s;
}
tr に :hover を指定すると、行全体の背景色をまとめて変えられます。tbody を頭に付けてヘッダー行が反応しないようにするのがコツです。列数の多い表では、視線が横にずれて別の行を読んでしまう事故が起きやすいため、この一行を入れるだけで読み間違いが目に見えて減ります。
:hover はマウスがある環境のための機能で、タッチ操作の端末では反応しないか、タップ後に色が残り続けます。ホバーはあくまで「あると便利な補助」として扱い、それがないと情報が読み取れない作りにはしないでください。
⑨ position: sticky — スクロールしてもヘッダーを固定する
| 月 | 売上 | 経費 | 利益 |
|---|---|---|---|
| 4月 | 50,000 | 40,000 | 10,000 |
| 5月 | 80,000 | 65,000 | 15,000 |
| 6月 | 40,000 | 32,000 | 8,000 |
| 7月 | 60,000 | 45,000 | 15,000 |
| 8月 | 75,000 | 57,000 | 18,000 |
| 9月 | 62,000 | 48,000 | 14,000 |
| 10月 | 91,000 | 70,000 | 21,000 |
| 11月 | 84,000 | 66,000 | 18,000 |
| 12月 | 120,000 | 88,000 | 32,000 |
| 1月 | 45,000 | 39,000 | 6,000 |
現在: position: sticky(ヘッダー固定)
<div class="table-scroll">
<table>
<thead>
<tr><th>月</th><th>売上</th><th>経費</th><th>利益</th></tr>
</thead>
<tbody>
<tr><td>4月</td><td>50,000</td><td>40,000</td><td>10,000</td></tr>
<tr><td>5月</td><td>80,000</td><td>65,000</td><td>15,000</td></tr>
<tr><td>6月</td><td>40,000</td><td>32,000</td><td>8,000</td></tr>
<tr><td>7月</td><td>60,000</td><td>45,000</td><td>15,000</td></tr>
<tr><td>8月</td><td>75,000</td><td>57,000</td><td>18,000</td></tr>
<tr><td>9月</td><td>62,000</td><td>48,000</td><td>14,000</td></tr>
<tr><td>10月</td><td>91,000</td><td>70,000</td><td>21,000</td></tr>
<tr><td>11月</td><td>84,000</td><td>66,000</td><td>18,000</td></tr>
<tr><td>12月</td><td>120,000</td><td>88,000</td><td>32,000</td></tr>
<tr><td>1月</td><td>45,000</td><td>39,000</td><td>6,000</td></tr>
</tbody>
</table>
</div>
.table-scroll {
max-height: 220px;
overflow-y: auto;
}
table {
border-collapse: collapse;
width: 100%;
}
thead th {
position: sticky;
top: 0;
z-index: 1;
background-color: #2563eb;
color: #fff;
padding: 8px 14px;
text-align: center;
box-shadow: inset 0 -2px 0 #1e40af;
}
tbody td {
border-bottom: 1px solid #e2e8f0;
padding: 8px 14px;
text-align: center;
}
thead ではなく th に position: sticky と top: 0 を指定します。そして、スクロールする親要素に max-height と overflow-y: auto が必要です。この2つが揃って初めて固定が働きます。「sticky を書いたのに動かない」場合は、親がスクロールしていないケースがほとんどです。
border-collapse: collapse を使うと、結合されたボーダーは table のものとして描画されるため、th だけが浮いても線は一緒に付いてきません。スクロール時にヘッダーの区切り線が消えて見えるのはこれが原因です。border ではなく box-shadow: inset 0 -2px 0 で下線を描くと、th 自身のスタイルになるため固定時もきれいに残ります。
よくある質問
セルを結合したら表が右にはみ出してしまいました。
結合した分だけ <td> を減らし忘れているのが原因です。4列の表で colspan="3" のセルを置いたなら、その行の <td> は3個ではなく「1個(結合セル)+残り1個」の計2個になります。rowspan も同様で、結合された2行目以降の行では左端のセルを書きません。⑥のデモで結合ありとなしを切り替えると、行あたりのセル数の違いが確認できます。
表の幅をスマホでも崩れないようにするには?
table を <div> で囲み、その div に overflow-x: auto を指定して横スクロールさせるのが最も確実です。列を減らしたり文字を小さくするより、素直にスクロールさせたほうが読みやすくなります。table 側に white-space: nowrap を足すと、セル内で不自然に改行されるのも防げます。⑤のデモで指定あり・なしを比較できます。
th と td はどう使い分けますか?
<th> は見出しのセル、<td> はデータのセルです。見た目を太字にしたいかどうかで選ぶものではなく、「そのセルが他のセルを説明する立場か」で決めます。列の見出しだけでなく、各行の左端にある項目名(月名や商品名など)も <th scope="row"> にするのが正しい書き方です。太字が不要なら CSS の font-weight: normal で調整してください。
position: sticky を指定したのにヘッダーが固定されません。
スクロールする親要素がないことが最大の原因です。sticky は「親のスクロール範囲内で位置を保つ」機能なので、max-height と overflow-y: auto を持つ親が必要です。また、指定先は <thead> ではなく <th> にしてください。祖先要素のどこかに overflow: hidden があると効かなくなる点にも注意が必要です。
当サイトで公開しているWebデザインやUIの実装例は、一覧として以下記事に纏めています。

