19. テーブル入門(table/thead/tbody/tr/th/td)
まず結論
表(行×列のデータ)は table と th/td で正しく組むと、読みやすく・読み上げにも強い表が作れます。
最小の書き方(コピペで動く最小コード)
HTMLCode
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Table Minimum</title>
</head>
<body>
<table>
<thead>
<tr>
<th>プラン</th>
<th>料金</th>
<th>対象</th>
</tr>
</thead>
<tbody>
<tr>
<td>ライト</td>
<td>1,000円</td>
<td>まず試したい</td>
</tr>
<tr>
<td>スタンダード</td>
<td>3,000円</td>
<td>しっかり使う</td>
</tr>
</tbody>
</table>
</body>
</html>
Previewdesktop
HTMLCode
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Table Minimum</title>
</head>
<body>
<table>
<thead>
<tr>
<th>プラン</th>
<th>料金</th>
<th>対象</th>
</tr>
</thead>
<tbody>
<tr>
<td>ライト</td>
<td>1,000円</td>
<td>まず試したい</td>
</tr>
<tr>
<td>スタンダード</td>
<td>3,000円</td>
<td>しっかり使う</td>
</tr>
</tbody>
</table>
</body>
</html>
Preview を表示
重要ポイント(ここで迷いがち)
- 表は“データ”のためのもの
- レイアウト目的で表を使わない(並べたいだけならCSSのgrid/flex)。
- 行はtr、見出しセルはth、データセルはtd
- thead/tbodyは“意味と整理”のため
- なくても動くけど、あると読みやすく保守もしやすい。
- thは見出し(ラベル)として重要
- 読み上げで「この値は何の列/行か」が伝わりやすい。
- よくある詰まり:thを全部tdで書いてしまう
- 見た目は近くても意味が落ちる。
例で理解(よく使うパターン 4つ)
1) 料金表(列見出し)
HTMLCode
<table>
<thead>
<tr>
<th>プラン</th>
<th>月額</th>
<th>サポート</th>
</tr>
</thead>
<tbody>
<tr>
<td>ライト</td>
<td>1,000円</td>
<td>メール</td>
</tr>
<tr>
<td>プロ</td>
<td>5,000円</td>
<td>チャット</td>
</tr>
</tbody>
</table>
Previewdesktop
HTMLCode
<table>
<thead>
<tr>
<th>プラン</th>
<th>月額</th>
<th>サポート</th>
</tr>
</thead>
<tbody>
<tr>
<td>ライト</td>
<td>1,000円</td>
<td>メール</td>
</tr>
<tr>
<td>プロ</td>
<td>5,000円</td>
<td>チャット</td>
</tr>
</tbody>
</table>
Preview を表示
2) 営業時間(行見出し:曜日がラベル)
HTMLCode
<table>
<tbody>
<tr>
<th>月</th>
<td>10:00–18:00</td>
</tr>
<tr>
<th>火</th>
<td>10:00–18:00</td>
</tr>
<tr>
<th>水</th>
<td>定休日</td>
</tr>
</tbody>
</table>
Previewdesktop
HTMLCode
<table>
<tbody>
<tr>
<th>月</th>
<td>10:00–18:00</td>
</tr>
<tr>
<th>火</th>
<td>10:00–18:00</td>
</tr>
<tr>
<th>水</th>
<td>定休日</td>
</tr>
</tbody>
</table>
Preview を表示
“左列がラベル”なら th を行の先頭に置くのが自然。
3) scopeで「どっちの見出しか」を明確に(おすすめ)
HTMLCode
<table>
<thead>
<tr>
<th scope="col">プラン</th>
<th scope="col">料金</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">ライト</th>
<td>1,000円</td>
</tr>
<tr>
<th scope="row">スタンダード</th>
<td>3,000円</td>
</tr>
</tbody>
</table>
Previewdesktop
HTMLCode
<table>
<thead>
<tr>
<th scope="col">プラン</th>
<th scope="col">料金</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">ライト</th>
<td>1,000円</td>
</tr>
<tr>
<th scope="row">スタンダード</th>
<td>3,000円</td>
</tr>
</tbody>
</table>
Preview を表示
- scope="col":列の見出し
- scope="row":行の見出し
4) キャプション(表のタイトル)を付ける
HTMLCode
<table>
<caption>料金プラン一覧</caption>
<thead>...</thead>
<tbody>...</tbody>
</table>
Previewdesktop
HTMLCode
<table>
<caption>料金プラン一覧</caption>
<thead>...</thead>
<tbody>...</tbody>
</table>
Preview を表示
何の表かが一瞬で分かり、アクセシビリティにも強い。
使い分け(似た要素との違い)
- 表(table) vs リスト(ul/ol)
- 行×列の対応がある → table
- ただ並ぶだけ → ul/ol
- 表(table) vs カード一覧(div)
- 比較・一覧性が重要(料金比較など) → table
- 文章中心・自由なレイアウト → カード(div/article)
- th vs td
- ラベル(見出し) → th
- 値(データ) → td
実務のコツ(SEO/安全/アクセシビリティ)
- captionは付けると強い(表の目的が伝わる)
- scopeを付けると読み上げが安定(列/行の関係が明確)
- スマホで横に溢れる表は“横スクロール”にする
- 無理に文字を小さくしない(下のCSS例でやる)。
- 表の中にボタンやリンクを入れるときは、操作対象が分かる文言に
- ×「詳細」→ ○「ライトプランの詳細」
NG・禁止例(事故る書き方)
NG1)表でレイアウトを作る(古い&崩れやすい)
HTMLCode
<table>
<tr>
<td>左カラム</td>
<td>右カラム</td>
</tr>
</table>
Previewdesktop
HTMLCode
<table>
<tr>
<td>左カラム</td>
<td>右カラム</td>
</tr>
</table>
Preview を表示
✅ 正:レイアウトはCSS(grid/flex)で
NG2)見出し行も全部td
HTMLCode
<tr>
<td>プラン</td>
<td>料金</td>
</tr>
※ このHTML断片は meta / title など表示要素がないため、プレビューは省略しました。
✅ 正:見出しはth
HTMLCode
<tr>
<th>プラン</th>
<th>料金</th>
</tr>
※ このHTML断片は meta / title など表示要素がないため、プレビューは省略しました。
NG3)tr直下に文字(セルを作らない)
HTMLCode
<tr>
プラン
</tr>
※ このHTML断片は meta / title など表示要素がないため、プレビューは省略しました。
✅ 正:th/tdのセルに入れる
NG4)行・列の対応が曖昧(データが読めない)
列数が揃っていない、ラベルが無い等
✅ 正:列/行のラベルを用意し、必要ならscopeを付ける
見た目を整える(HTML+CSSセット:5例)
色は使わず、線・余白・影・スクロールで整えます。
例1)基本の“読みやすい表”
例1)基本の“読みやすい表”
HTMLCode
<div class="table-wrap">
<table class="table">
<caption>料金プラン一覧</caption>
<thead>
<tr>
<th scope="col">プラン</th>
<th scope="col">料金</th>
<th scope="col">対象</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">ライト</th>
<td>1,000円</td>
<td>まず試したい</td>
</tr>
<tr>
<th scope="row">スタンダード</th>
<td>3,000円</td>
<td>しっかり使う</td>
</tr>
<tr>
<th scope="row">プロ</th>
<td>5,000円</td>
<td>がっつり使う</td>
</tr>
</tbody>
</table>
</div>CSSCode
.table-wrap{ max-width: 920px; }
.table{
width: 100%;
border-collapse: collapse;
}
.table caption{
text-align: left;
font-weight: 600;
margin: 0 0 .6rem;
}
.table th, .table td{
padding: .75rem .9rem;
border-bottom: 1px solid rgba(0,0,0,.16);
text-align: left;
vertical-align: top;
}
.table thead th{
border-bottom: 2px solid rgba(0,0,0,.22);
}Previewdesktop
HTMLCode
<div class="table-wrap">
<table class="table">
<caption>料金プラン一覧</caption>
<thead>
<tr>
<th scope="col">プラン</th>
<th scope="col">料金</th>
<th scope="col">対象</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">ライト</th>
<td>1,000円</td>
<td>まず試したい</td>
</tr>
<tr>
<th scope="row">スタンダード</th>
<td>3,000円</td>
<td>しっかり使う</td>
</tr>
<tr>
<th scope="row">プロ</th>
<td>5,000円</td>
<td>がっつり使う</td>
</tr>
</tbody>
</table>
</div>CSSCode
.table-wrap{ max-width: 920px; }
.table{
width: 100%;
border-collapse: collapse;
}
.table caption{
text-align: left;
font-weight: 600;
margin: 0 0 .6rem;
}
.table th, .table td{
padding: .75rem .9rem;
border-bottom: 1px solid rgba(0,0,0,.16);
text-align: left;
vertical-align: top;
}
.table thead th{
border-bottom: 2px solid rgba(0,0,0,.22);
}Preview を表示
例2)ゼブラ(交互)で行を追いやすく(薄い影で)
例2)ゼブラ(交互)で行を追いやすく
HTMLCode
<table class="table zebra">
<caption>オプション一覧</caption>
<thead>
<tr>
<th scope="col">項目</th>
<th scope="col">内容</th>
</tr>
</thead>
<tbody>
<tr><th scope="row">メール</th><td>24時間以内に返信</td></tr>
<tr><th scope="row">チャット</th><td>平日 10:00–18:00</td></tr>
<tr><th scope="row">電話</th><td>予約制</td></tr>
<tr><th scope="row">訪問</th><td>別途見積</td></tr>
</tbody>
</table>CSSCode
.table{
width: 100%;
border-collapse: collapse;
}
.table caption{
text-align: left;
font-weight: 600;
margin: 0 0 .6rem;
}
.table th, .table td{
padding: .75rem .9rem;
border-bottom: 1px solid rgba(0,0,0,.16);
text-align: left;
}
.table thead th{
border-bottom: 2px solid rgba(0,0,0,.22);
}
.zebra tbody tr:nth-child(even){
box-shadow: inset 0 0 0 9999px rgba(0,0,0,.03);
}Previewdesktop
HTMLCode
<table class="table zebra">
<caption>オプション一覧</caption>
<thead>
<tr>
<th scope="col">項目</th>
<th scope="col">内容</th>
</tr>
</thead>
<tbody>
<tr><th scope="row">メール</th><td>24時間以内に返信</td></tr>
<tr><th scope="row">チャット</th><td>平日 10:00–18:00</td></tr>
<tr><th scope="row">電話</th><td>予約制</td></tr>
<tr><th scope="row">訪問</th><td>別途見積</td></tr>
</tbody>
</table>CSSCode
.table{
width: 100%;
border-collapse: collapse;
}
.table caption{
text-align: left;
font-weight: 600;
margin: 0 0 .6rem;
}
.table th, .table td{
padding: .75rem .9rem;
border-bottom: 1px solid rgba(0,0,0,.16);
text-align: left;
}
.table thead th{
border-bottom: 2px solid rgba(0,0,0,.22);
}
.zebra tbody tr:nth-child(even){
box-shadow: inset 0 0 0 9999px rgba(0,0,0,.03);
}Preview を表示
例3)スマホ対策:横スクロールにする(最重要)
例3)スマホ対策:横スクロールにする(最重要)
HTMLCode
<div class="table-scroll" role="region" aria-label="横スクロールできる表">
<table class="table">
<caption>比較表(列が多い例)</caption>
<thead>
<tr>
<th scope="col">プラン</th>
<th scope="col">料金</th>
<th scope="col">サポート</th>
<th scope="col">容量</th>
<th scope="col">備考</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">ライト</th>
<td>1,000円</td>
<td>メール</td>
<td>5GB</td>
<td>まず試す</td>
</tr>
<tr>
<th scope="row">プロ</th>
<td>5,000円</td>
<td>チャット</td>
<td>50GB</td>
<td>本格運用</td>
</tr>
</tbody>
</table>
</div>CSSCode
.table{
width: 100%;
border-collapse: collapse;
}
.table caption{
text-align: left;
font-weight: 600;
margin: 0 0 .6rem;
}
.table th, .table td{
padding: .75rem .9rem;
border-bottom: 1px solid rgba(0,0,0,.16);
text-align: left;
vertical-align: top;
}
.table thead th{
border-bottom: 2px solid rgba(0,0,0,.22);
}
.table-scroll{
overflow-x: auto;
-webkit-overflow-scrolling: touch;
border: 1px solid rgba(0,0,0,.14);
border-radius: 16px;
padding: .2rem;
}
.table-scroll .table{
min-width: 560px;
}Previewdesktop
HTMLCode
<div class="table-scroll" role="region" aria-label="横スクロールできる表">
<table class="table">
<caption>比較表(列が多い例)</caption>
<thead>
<tr>
<th scope="col">プラン</th>
<th scope="col">料金</th>
<th scope="col">サポート</th>
<th scope="col">容量</th>
<th scope="col">備考</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">ライト</th>
<td>1,000円</td>
<td>メール</td>
<td>5GB</td>
<td>まず試す</td>
</tr>
<tr>
<th scope="row">プロ</th>
<td>5,000円</td>
<td>チャット</td>
<td>50GB</td>
<td>本格運用</td>
</tr>
</tbody>
</table>
</div>CSSCode
.table{
width: 100%;
border-collapse: collapse;
}
.table caption{
text-align: left;
font-weight: 600;
margin: 0 0 .6rem;
}
.table th, .table td{
padding: .75rem .9rem;
border-bottom: 1px solid rgba(0,0,0,.16);
text-align: left;
vertical-align: top;
}
.table thead th{
border-bottom: 2px solid rgba(0,0,0,.22);
}
.table-scroll{
overflow-x: auto;
-webkit-overflow-scrolling: touch;
border: 1px solid rgba(0,0,0,.14);
border-radius: 16px;
padding: .2rem;
}
.table-scroll .table{
min-width: 560px;
}Preview を表示
例4)セルの“数字”を揃える(右寄せ)
例4)セルの“数字”を揃える(右寄せ)
HTMLCode
<table class="table">
<caption>数値が混ざる表</caption>
<thead>
<tr>
<th scope="col">項目</th>
<th scope="col" class="num">値</th>
</tr>
</thead>
<tbody>
<tr><th scope="row">人数</th><td class="num">12</td></tr>
<tr><th scope="row">回数</th><td class="num">3</td></tr>
<tr><th scope="row">合計</th><td class="num">15</td></tr>
</tbody>
</table>CSSCode
.table{
width: 100%;
border-collapse: collapse;
}
.table caption{
text-align: left;
font-weight: 600;
margin: 0 0 .6rem;
}
.table th, .table td{
padding: .75rem .9rem;
border-bottom: 1px solid rgba(0,0,0,.16);
text-align: left;
}
.table thead th{
border-bottom: 2px solid rgba(0,0,0,.22);
}
.num{
text-align: right;
font-variant-numeric: tabular-nums;
}Previewdesktop
HTMLCode
<table class="table">
<caption>数値が混ざる表</caption>
<thead>
<tr>
<th scope="col">項目</th>
<th scope="col" class="num">値</th>
</tr>
</thead>
<tbody>
<tr><th scope="row">人数</th><td class="num">12</td></tr>
<tr><th scope="row">回数</th><td class="num">3</td></tr>
<tr><th scope="row">合計</th><td class="num">15</td></tr>
</tbody>
</table>CSSCode
.table{
width: 100%;
border-collapse: collapse;
}
.table caption{
text-align: left;
font-weight: 600;
margin: 0 0 .6rem;
}
.table th, .table td{
padding: .75rem .9rem;
border-bottom: 1px solid rgba(0,0,0,.16);
text-align: left;
}
.table thead th{
border-bottom: 2px solid rgba(0,0,0,.22);
}
.num{
text-align: right;
font-variant-numeric: tabular-nums;
}Preview を表示
例5)表の“フォーカス見え”を強化(リンクがある場合)
例5)表の“フォーカス見え”を強化(リンクがある場合)
HTMLCode
<table class="table">
<caption>プラン詳細</caption>
<tbody>
<tr>
<th scope="row">ライト</th>
<td><a class="rowlink" href="/plan/light.html">ライトプランの詳細を見る</a></td>
</tr>
<tr>
<th scope="row">スタンダード</th>
<td><a class="rowlink" href="/plan/standard.html">スタンダードの詳細を見る</a></td>
</tr>
</tbody>
</table>CSSCode
.table{
width: 100%;
border-collapse: collapse;
}
.table caption{
text-align: left;
font-weight: 600;
margin: 0 0 .6rem;
}
.table th, .table td{
padding: .75rem .9rem;
border-bottom: 1px solid rgba(0,0,0,.16);
text-align: left;
vertical-align: top;
}
.rowlink{
text-decoration: underline;
text-underline-offset: 4px;
}
.rowlink:focus-visible{
outline: 3px solid currentColor;
outline-offset: 3px;
border-radius: 8px;
}Previewdesktop
HTMLCode
<table class="table">
<caption>プラン詳細</caption>
<tbody>
<tr>
<th scope="row">ライト</th>
<td><a class="rowlink" href="/plan/light.html">ライトプランの詳細を見る</a></td>
</tr>
<tr>
<th scope="row">スタンダード</th>
<td><a class="rowlink" href="/plan/standard.html">スタンダードの詳細を見る</a></td>
</tr>
</tbody>
</table>CSSCode
.table{
width: 100%;
border-collapse: collapse;
}
.table caption{
text-align: left;
font-weight: 600;
margin: 0 0 .6rem;
}
.table th, .table td{
padding: .75rem .9rem;
border-bottom: 1px solid rgba(0,0,0,.16);
text-align: left;
vertical-align: top;
}
.rowlink{
text-decoration: underline;
text-underline-offset: 4px;
}
.rowlink:focus-visible{
outline: 3px solid currentColor;
outline-offset: 3px;
border-radius: 8px;
}Preview を表示
理解チェック(3問・答え付き)
Q. 行×列の“データ”を表すなら ul と table どっち?
A. table。
Q. 見出しセルは th と td どっち?
A. th。
Q. スマホで表がはみ出すときの安全策は?
A. 表を包んで overflow-x: auto; で横スクロールにする。
ミニ演習(すぐ試せる小課題 2つ)
- 「料金プラン表」を作ってください。
列:プラン / 料金 / 対象
行:ライト / スタンダード / プロ(3行)
caption と scope も付ける(例1を参考に) - 列が多い表(例:項目を5列)を作り、CSS例3の“横スクロール”を適用して、スマホでも崩れないことを確認してください。