テーブルの作り方 実装解説|HTML CSS Table Guide

テーブル デザイン見本

HTML の <table> 要素と CSS を組み合わせた表スタイルの実装デモ。ボタンで見た目の違いをリアルタイムで確認しながら、コピーしてすぐに使えるコードを掲載しています。
HTML・CSS・JSコードプレビューツール にて実装確認ができます。

① border-collapse — セルのボーダーを結合・分離する

売上経費利益
4月50,00040,00010,000
5月80,00065,00015,000
6月40,00032,0008,000
7月60,00045,00015,000

現在: border-collapse: collapse

HTML
<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>
CSS
table {
  border-collapse: collapse;
  width: 100%;
}

th, td {
  border: 1px solid #64748b;
  padding: 8px 14px;
  text-align: center;
}
border-collapse: collapse

デフォルト値は separate(各セルのボーダーが独立して描画されるため二重線になる)。collapse を指定すると隣り合うセルのボーダーが1本に統合され、すっきりした表になります。実務ではほぼすべてのケースで collapse を使うのが一般的です。

② ヘッダースタイル — 罫線 / 太い区切り / カラーヘッダー

売上経費利益
4月50,00040,00010,000
5月80,00065,00015,000
6月40,00032,0008,000
7月60,00045,00015,000

現在: 罫線のみ

HTML
<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>
CSS
table {
  border-collapse: collapse;
  width: 100%;
}

th, td {
  border: 1px solid #475569;
  padding: 8px 14px;
  text-align: center;
}
<thead> でヘッダー行を区別する

<thead> と <tbody> を使い分けると、CSS でヘッダー行だけにスタイルを当てやすくなります。「太い区切り線」は thead に border-bottom を指定するだけでヘッダーと本文の境界を強調でき、スタイリッシュな表が簡単に作れます。

③ ストライプ — :nth-child で交互に背景色を付ける

売上経費利益
4月50,00040,00010,000
5月80,00065,00015,000
6月40,00032,0008,000
7月60,00045,00015,000

現在: 奇数行 (odd) に背景色

HTML
<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>
CSS
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;
}
:nth-child(odd) / :nth-child(even)

tbody の tr に :nth-child(odd) を指定すると奇数行(1・3・5…行目)に、even を指定すると偶数行に背景色が付きます。行数が多い表では縞模様にするだけで視認性が大幅に上がります。thead の th には別途スタイルを設定することでヘッダー行と本文を明確に区別できます。

④ ヘッダーなしテーブル — <tbody> のみで構成する

4月50,00040,00010,000
5月80,00065,00015,000
6月40,00032,0008,000
7月60,00045,00015,000

現在: 罫線スタイル

HTML
<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>
CSS
table {
  border-collapse: collapse;
  width: 100%;
}

td {
  border: 1px solid #475569;
  padding: 8px 14px;
  text-align: center;
}
<thead> を省略する場合

<thead> を省いて <tbody> だけにすると、すべての行が同じスタイルになるシンプルなヘッダーなし表を作れます。CSS のスタイルは th ではなく td のみに指定します。名簿・住所録など、全行が同じ種類のデータを並べる場合に向いています。

⑤ レスポンシブ対応 — overflow-x: auto でスマホに対応

売上(円)経費(円)利益(円)前月比備考
4月50,00040,00010,000開始月
5月80,00065,00015,000+50%好調
6月40,00032,0008,000-47%低調
7月60,00045,00015,000+88%回復

現在: overflow-x: auto(横スクロール可能)

HTML
<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>
CSS
.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;
}
overflow-x: auto でスマホ対応

列数が多い表はスマホ幅で崩れがちです。table を div でラップし、div に overflow-x: auto を指定すると、表が狭い画面でも横スクロールで閲覧できます。table 自体に white-space: nowrap を追加するとセル内でのテキスト折り返しを防ぎ、レイアウトが崩れにくくなります。

⑥ colspan / rowspan — セルを結合する

売上経費利益
4月50,00040,00010,000
5月80,00065,00015,000
6月40,00032,0008,000
2026年 上期 売上実績
売上経費利益
4月50,00040,00010,000
5月80,00065,00015,000
6月40,00032,0008,000
合計33,000
四半期売上利益
第1四半期4月50,00010,000
5月80,00015,000
6月40,0008,000
第2四半期7月60,00015,000
8月75,00018,000

現在: 結合なし

HTML
<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>
CSS
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 — 隣り合うセルをつなげる

colspan は横方向、rowspan は縦方向にセルを結合する属性です。CSS ではなく HTML 側の属性で指定します。表の上部にタイトル行を置く、最下部に合計行を置く、左端でカテゴリをまとめる、といった実務でよくある表現がこれだけで作れます。

結合した分だけ td を減らすのが最大のポイント

colspan=”3″ を指定したセルは3列分を占めるため、その行に書く td は「4個ではなく2個」になります。rowspan も同じで、結合された2行目以降では左端の td を書きません。ここを減らし忘れると、その行だけ列が1つ多くなって表が右にはみ出します。「セル結合したら表が崩れた」という失敗のほぼすべてがこれです。

⑦ caption / scope — 表にタイトルを付け、読み上げに対応する

2026年 上期 売上実績(単位:円)
売上経費利益
4月50,00040,00010,000
5月80,00065,00015,000
6月40,00032,0008,000

現在: caption-side: top

HTML
<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>
CSS
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 の中に書く

caption は table 直下の先頭に置く専用のタイトル要素です。表のすぐ上に p タグで見出しを置くのと違い、「この文章はこの表のタイトルである」という関係がブラウザと支援技術に正しく伝わります。caption-side: bottom を指定すれば、見た目だけ表の下に移動できます。

scope — どのセルの見出しなのかを明示する

scope=”col” は「この th は縦一列の見出し」、scope=”row” は「この th は横一行の見出し」という意味です。画面で見れば一目でわかる関係も、スクリーンリーダーは推測でしか判断できません。scope があると「4月の、利益は、10,000」のようにセルと見出しを結び付けて読み上げられます。見た目は一切変わりませんが、表のアクセシビリティはこの一手間でほぼ決まります。

⑧ tr:hover — マウスを乗せた行を強調する

売上経費利益
4月50,00040,00010,000
5月80,00065,00015,000
6月40,00032,0008,000
7月60,00045,00015,000

現在: ホバー効果なし

HTML
<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>
CSS
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;
}
tbody tr:hover — 行単位で強調する

tr に :hover を指定すると、行全体の背景色をまとめて変えられます。tbody を頭に付けてヘッダー行が反応しないようにするのがコツです。列数の多い表では、視線が横にずれて別の行を読んでしまう事故が起きやすいため、この一行を入れるだけで読み間違いが目に見えて減ります。

スマホでは効かないことを前提にする

:hover はマウスがある環境のための機能で、タッチ操作の端末では反応しないか、タップ後に色が残り続けます。ホバーはあくまで「あると便利な補助」として扱い、それがないと情報が読み取れない作りにはしないでください。

⑨ position: sticky — スクロールしてもヘッダーを固定する

売上経費利益
4月50,00040,00010,000
5月80,00065,00015,000
6月40,00032,0008,000
7月60,00045,00015,000
8月75,00057,00018,000
9月62,00048,00014,000
10月91,00070,00021,000
11月84,00066,00018,000
12月120,00088,00032,000
1月45,00039,0006,000

現在: position: sticky(ヘッダー固定)

HTML
<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>
CSS
.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;
}
position: sticky は th に指定する

thead ではなく th に position: sticky と top: 0 を指定します。そして、スクロールする親要素に max-height と overflow-y: auto が必要です。この2つが揃って初めて固定が働きます。「sticky を書いたのに動かない」場合は、親がスクロールしていないケースがほとんどです。

ヘッダーの下線が消えるのは border-collapse のせい

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-heightoverflow-y: auto を持つ親が必要です。また、指定先は <thead> ではなく <th> にしてください。祖先要素のどこかに overflow: hidden があると効かなくなる点にも注意が必要です。

レイアウトの目的で table を使ってもいいですか?

避けてください。<table> は「表形式のデータ」を表すための要素で、スクリーンリーダーは中身を行と列の関係として読み上げます。見た目を整える目的で使うと、意味のない構造が読み上げられてしまいます。ページの骨格や要素の配置には GridFlexbox を使ってください。


当サイトで公開しているWebデザインやUIの実装例は、一覧として以下記事に纏めています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次