HTMLで表を作るときに、<tbody>というタグを見かけることがあります。しかし、「tbodyタグは必要なの?」「書かなくても表示されるならいらないのでは?」「コードに書いていないのに検証画面でtbodyが勝手に入っているのはなぜ?」と疑問に感じる方も多いはずです。
tbodyタグは、HTMLテーブルの本体データ行をまとめるためのタグです。省略しても表示される場合がありますが、CSSやJavaScriptで表を扱うときのトラブルを防ぐため、実務では明示的に書くのがおすすめです。
この記事では、「html tbody」と調べている方に向けて、tbodyタグの役割、必要性、ブラウザが自動生成する理由、table > trでCSSが効かない落とし穴、複数tbodyの使い方まで解説します。
忍者CODEマガジンは、未経験からでもプロのエンジニアを目指せるプログラミングスクール「忍者CODE」が運営しているプログラミング情報サイトです。
- プログラミングの効果的な学習方法
- プログラミング用語の解説
- エンジニアのキャリアに関する情報
など、プログラミングを始めたばかりの初学者に役立つ記事を幅広く公開しています。
HTMLのtbodyタグとは?
tbodyタグは、テーブルの本体部分にあたる行をまとめるHTMLタグです。読み方は「ティーボディ」で、table bodyの略として覚えると分かりやすいです。
<table>
<thead>
<tr>
<th>タグ</th>
<th>役割</th>
</tr>
</thead>
<tbody>
<tr>
<td>tbody</td>
<td>テーブル本体の行をまとめる</td>
</tr>
</tbody>
</table>
この例では、theadに見出し行、tbodyに本体データ行を入れています。tbodyの中には、直接tdを書くのではなく、trタグで行を作り、その中にtdやthを入れます。
tbodyは「表の本体データ」をまとめる
テーブルは、大きく分けると次の3つのグループにできます。
| タグ | 役割 | 入れる内容 |
|---|---|---|
<thead> |
見出し行をまとめる | 列名、項目名 |
<tbody> |
本体データ行をまとめる | 通常のデータ |
<tfoot> |
末尾行をまとめる | 合計、注釈、集計 |
tbodyタグは見た目を変えるためのタグではありません。表の本体部分をHTML構造として分けるためのタグです。
tbodyの中に入るのはtrタグ
tbodyの中には、0個以上のtrタグを入れます。tdやthはtrタグの中に入れます。
<tbody>
<td>HTML</td>
<td>構造を作る</td>
</tbody>
<tbody>
<tr>
<td>HTML</td>
<td>構造を作る</td>
</tr>
</tbody>
tbodyは行グループ、trは行、td・thはセルと分けて覚えると整理しやすくなります。
tbodyはいらない?必要性と書くメリット
結論からいうと、tbodyを書かなくても表が表示されるケースはあります。ただし、HTML構造、CSS、JavaScriptの扱いやすさを考えると、tbodyは省略せずに書くのがおすすめです。
tbodyを書かなくても表示されることはある
次のように、table直下にtrを書いても、多くのブラウザでは表として表示されます。
<table>
<tr>
<td>HTML</td>
<td>構造を作る</td>
</tr>
</table>
表示されるため、「tbodyはいらないのでは?」と思うかもしれません。しかし、ブラウザ内部のDOMではtbodyが補われることがあり、CSSやJavaScriptで意図しないズレが起きる原因になります。表示されることと、管理しやすいHTMLであることは別です。実務ではtbodyを明示的に書く方が安全です。
tbodyを書くと構造が読みやすくなる
tbodyを明示することで、開発者がコードを読みやすくなるだけでなく、音声読み上げブラウザ(スクリーンリーダー)などの支援技術が表のデータ構造を正しく解釈しやすくなるというメリット(アクセシビリティの向上)もあります。
<table>
<thead>
<tr>
<th>項目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML</td>
<td>Webページの構造</td>
</tr>
</tbody>
</table>
tbodyは「表の本体データはここからここまで」と示す目印になります。
関連記事:「HTMLのtrタグとは?td・thとの違いや使い方を解説」
メリット①:JavaScriptで表のデータだけを狙い撃ちできる
tbodyを書く大きなメリットの1つが、JavaScriptで表の本体データだけを扱いやすくなることです。
tbody内の行だけを取得する
たとえば、見出し行を除いて、データ行だけを取得したい場合があります。
<table id="course-table">
<thead>
<tr>
<th>講座</th>
<th>料金</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML講座</td>
<td>無料</td>
</tr>
<tr>
<td>CSS講座</td>
<td>無料</td>
</tr>
</tbody>
</table>
const rows = document.querySelectorAll("#course-table tbody tr");
rows.forEach((row) => {
console.log(row.textContent);
});
このように書くと、theadの見出し行を除外して、tbody内のデータ行だけを取得できます。
tbodyを明示しておくと、JavaScriptで「表の本体だけ」を指定しやすくなります。
実務でよくある使い道
制作現場では、tbodyを使って次のような処理を行うことがあります。
- 検索結果テーブルのデータ行だけを更新する
- 一覧表に新しい行を追加する
- チェックされた行だけを取得する
- 合計金額を再計算する
const tbody = document.querySelector("#course-table tbody");
const newRow = document.createElement("tr");
newRow.innerHTML = "<td>JavaScript講座</td><td>無料</td>";
tbody.appendChild(newRow);
tbodyがあると、見出し行に影響を与えずにデータ行だけを追加できます。
JavaScriptでtable全体を雑に操作すると、theadやtfootまで巻き込んでしまうことがあります。データ行だけを触りたい場合はtbodyを基準にしましょう。
メリット②:CSSで「ヘッダー以外」に一括でスタイルを当てられる
tbodyを使うと、CSSで表の本体部分だけにスタイルを当てやすくなります。特に、ヘッダー行を除いて背景色や余白を調整したいときに便利です。
tbodyだけに背景色を付ける
.course-table thead {
background-color: #f0f0f0;
}
.course-table tbody {
background-color: #fff;
}
このように書くと、見出し部分と本体部分の装飾を分けられます。
データ行だけ一行おきに色を変える
tbodyがあると、見出し行を含めずにデータ行だけをストライプ表示できます。
.course-table tbody tr:nth-child(even) {
background-color: #f7f7f7;
}
theadを含めずにtbody内だけを数えるため、色の付き方がずれにくくなります。
tbodyを使えば、ヘッダー以外の本体行だけにCSSを当てやすくなります。
tbodyを省略するとCSSの指定が分かりにくくなる
tbodyを書かずにtable直下のtrを狙おうとすると、後述する自動補完の影響でCSSが効かない場合があります。
table > tr {
background-color: #f7f7f7;
}
この指定は、「tableの直接の子であるtr」を選ぶCSSです。しかしブラウザがtbodyを補うと、trはtableの直接の子ではなく、tbodyの子になります。
CSSで表の行を安定して指定したいなら、tbodyを明示してtbody trのように書く方が安全です。
コードに書いていないのにtbodyが勝手に入る原因
HTMLを書いていると、コードにはtbodyを書いていないのに、ブラウザの検証画面ではtbodyが表示されることがあります。これはバグではありません。ブラウザがHTMLを解釈するときに、テーブル構造を補ってDOMを作っているためです。
ブラウザが親切心で自動補完してしまう仕様
たとえば、次のようにtbodyを書かずにtable直下へtrを書いたとします。
<table>
<tr>
<td>HTML</td>
<td>構造を作る</td>
</tr>
</table>
ブラウザの検証画面では、次のようにtbodyが入って見えることがあります。
<table>
<tbody>
<tr>
<td>HTML</td>
<td>構造を作る</td>
</tr>
</tbody>
</table>
MDNでも、tr要素をtableの直接の子として書いた場合、ブラウザがそれらを囲むtbody要素を生成することがあると説明されています。
コードにtbodyを書いていなくても、ブラウザのDOM上ではtbodyが補われることがあります。
HTMLソースと検証画面が違って見える理由
「ページのソースを表示」で見えるHTMLは、自分が書いた元のHTMLに近いものです。一方、開発者ツールのElementsで見える内容は、ブラウザが解釈した後のDOMです。そのため、tbodyのようにブラウザが補った要素は、開発者ツールでは見えるのに、元のHTMLファイルには書かれていないことがあります。
検証画面にtbodyがあるからといって、誰かが勝手にファイルを書き換えたわけではありません。ブラウザの解釈後の構造として表示されています。
【重要】table > trでCSSが効かなくなる落とし穴と対策
tbodyが自動生成されることを知らないと、CSSでつまずきやすくなります。代表例が、table > trというセレクタです。
table > trが効かない理由
>は「直接の子要素」を指定するCSSセレクタです。
table > tr {
background-color: #f7f7f7;
}
このCSSは「tableの直下にあるtr」を指定しています。しかし、ブラウザがtbodyを補うと、実際のDOMは次のようになります。
<table>
<tbody>
<tr>
<td>HTML</td>
</tr>
</tbody>
</table>
この場合、trはtableの直接の子ではなく、tbodyの子です。そのため、table > trは当たりません。
tbodyを省略したテーブルでtable > trが効かない場合、ブラウザがtbodyを補っている可能性があります。
対策:tbody trを指定する
表の本体行を指定したい場合は、tbodyを明示し、CSSでもtbody trを指定しましょう。
<table class="course-table">
<tbody>
<tr>
<td>HTML</td>
<td>構造を作る</td>
</tr>
</tbody>
</table>
.course-table tbody tr {
background-color: #f7f7f7;
}
テーブルの行にCSSを当てるときは、tbodyを省略せずに書き、CSSでもtbody trを指定すると安定します。
実務Tips:開発者ツールでDOMを確認する
CSSが効かないときは、ブラウザの開発者ツールでtableの中身を確認しましょう。自分ではtbodyを書いていなくても、Elements上ではtbodyが追加されていることがあります。
- HTMLファイル:tbodyを書いていない
- 開発者ツール:tbodyが表示されている
- CSS:table > trではなくtbody trを使う
【応用】1つのテーブルの中にtbodyを複数使ってもいいの?
tbodyは、1つのtableの中で複数使うことができます。大きな表でデータのグループが分かれている場合に便利です。
データのグループが複数に分かれる場合の正しい書き方
たとえば、講座一覧を「HTML/CSS」と「JavaScript」で分けたい場合は、tbodyを複数使ってグループ化できます。
<table class="group-table">
<thead>
<tr>
<th scope="col">講座</th>
<th scope="col">内容</th>
</tr>
</thead>
<tbody>
<tr>
<th colspan="2">HTML/CSS</th>
</tr>
<tr>
<td>HTML入門</td>
<td>タグの基本を学ぶ</td>
</tr>
<tr>
<td>CSS入門</td>
<td>見た目の調整を学ぶ</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="2">JavaScript</th>
</tr>
<tr>
<td>JavaScript入門</td>
<td>動きを付ける基本を学ぶ</td>
</tr>
</tbody>
</table>
このように、tbodyを複数使うことで、表の本体データを意味のあるまとまりに分けられます。
複数tbodyは連続して書く
複数のtbodyを使う場合は、tbody同士を連続して書きます。間にtheadやtfootを挟むような書き方は避けましょう。
<table>
<thead>...</thead>
<tbody>...</tbody>
<tbody>...</tbody>
<tfoot>...</tfoot>
</table>
MDNでも、1つのtable内で複数のtbodyを使えるが、それらは連続している必要があると説明されています。
データのグループが複数に分かれる表では、tbodyを複数使って構造を分けても問題ありません。
tbodyごとにCSSを変える
tbodyにclassを付ければ、グループごとに色や余白を変えられます。
<tbody class="html-css-group">...</tbody>
<tbody class="js-group">...</tbody>
.html-css-group {
background-color: #f7fbff;
}
.js-group {
background-color: #fffdf2;
}
ただし、グループ分けが不要な小さな表でtbodyを細かく分けすぎると、かえって読みづらくなります。
テーブルの構造を理解するために一緒に学ぶべきタグ
tbodyを理解すると、HTMLテーブルの構造がかなり整理しやすくなります。あわせて、trとtheadのに関しても学ぶと、表の「行」「見出し」「本体」の関係がつながります。
- tr:横1行を作るタグ
- thead:見出し行をまとめるタグ
- tbody:本体データ行をまとめるタグ
公式ドキュメントも確認する
tbodyや関連するテーブル要素の仕様を正確に確認したい場合は、公式ドキュメントも参考になります。
- HTML・CSSを学んで自分だけのスキルを身につけたい
- HTML・CSSのスキルを身につけてwebクリエイターとして活躍したい
- サポートが充実しているプログラミングスクールを知りたい
そんな思いを持った方は忍者CODEのWeb制作コースがおすすめです!
忍者CODEは未経験からでもプロのエンジニアを目指せるオンラインプログラミングスク―ルです。
期間制限なく動画を視聴できるので、自分のペースで学習することができます!
まとめ:トラブルを防ぐためにもtbodyは省略せずに書こう!
この記事では、HTMLのtbodyタグについて解説しました。
tbodyタグは、テーブルの本体データ行をまとめるためのタグです。tbodyを書かなくても表が表示されることはありますが、ブラウザが自動的にtbodyを補うことがあります。その結果、table > trのようなCSSが効かない、JavaScriptで狙った行を取得しにくい、といったトラブルにつながる場合があります。
JavaScriptで本体データだけを操作したいとき、CSSでヘッダー以外にスタイルを当てたいとき、大きな表を複数グループに分けたいときは、tbodyを明示しておくと管理しやすくなります。HTMLテーブルをきれいに作るなら、trで行を作り、theadで見出し行をまとめ、tbodyで本体データをまとめる流れを覚えておきましょう。
関連記事:「HTMLのtrタグとは?td・thとの違いや使い方を解説」



