Table Sections: <thead>, <tbody>, and <tfoot>
A basic table works fine for a few rows. Once a table grows — or needs to communicate clearly to screen readers and developers — you divide it into sections using <thead>, <tbody>, and <tfoot>.
The three section elements
Section titled “The three section elements”| Element | Purpose |
|---|---|
<thead> | Groups the header row(s) — the labels |
<tbody> | Groups the main data rows |
<tfoot> | Groups a summary or footer row at the bottom |
These elements wrap <tr> rows. The hierarchy becomes: <table> → <thead> / <tbody> / <tfoot> → <tr> → <td> / <th>.
A table without sections (from Lesson 01)
Section titled “A table without sections (from Lesson 01)”<table> <tr> <th>Rating</th> <th>Typical Distance</th> </tr> <tr> <td>Easy</td> <td>Under 5 miles</td> </tr> <tr> <td>Moderate</td> <td>5–10 miles</td> </tr></table>This works, but there is no explicit separation between the header row and the data rows.
The same table with sections
Section titled “The same table with sections”<table> <thead> <tr> <th>Rating</th> <th>Typical Distance</th> </tr> </thead> <tbody> <tr> <td>Easy</td> <td>Under 5 miles</td> </tr> <tr> <td>Moderate</td> <td>5–10 miles</td> </tr> <tr> <td>Strenuous</td> <td>Over 10 miles</td> </tr> </tbody></table>The structure is now explicit. Any developer reading the HTML — or any screen reader scanning it — immediately understands which rows are headers and which are data.
Adding <tfoot>
Section titled “Adding <tfoot>”<tfoot> holds a summary, total, or note row at the bottom of the table. It is optional but useful when the last row has a different meaning than the data rows above it.
<table> <thead> <tr> <th>Trail</th> <th>Distance (miles)</th> </tr> </thead> <tbody> <tr> <td>Pine Ridge Loop</td> <td>4.2</td> </tr> <tr> <td>Summit Approach</td> <td>8.7</td> </tr> <tr> <td>Valley Floor Trail</td> <td>2.1</td> </tr> </tbody> <tfoot> <tr> <td>Total</td> <td>15.0</td> </tr> </tfoot></table>The total row is semantically different from the data rows — <tfoot> makes that distinction explicit.
What sections do (and don’t) change
Section titled “What sections do (and don’t) change”Adding <thead>, <tbody>, and <tfoot> does not change the visual appearance by default. The table looks identical with or without them. What they do change:
- Readability — the HTML communicates intent more clearly
- Accessibility — screen readers use section context to describe rows
- CSS targeting — you can style
thead,tbody, andtfootseparately without class names - Browser behavior — some browsers allow
tbodyto scroll independently whiletheadandtfootremain fixed (relevant once you learn CSS)
Exercise
Section titled “Exercise”Open index.html in VS Code.
Find the <table> you built in Lesson 01. You are going to wrap its rows in <thead> and <tbody> sections.
- Identify your header row (the one with
<th>cells). - Wrap that row in
<thead>…</thead>. - Wrap all the data rows in
<tbody>…</tbody>. - If your table has a summary or total row at the bottom, wrap that in
<tfoot>…</tfoot>.
Before:
<table> <tr> <th>Rating</th> <th>Typical Distance</th> </tr> <tr> <td>Easy</td> <td>Under 5 miles</td> </tr></table>After:
<table> <thead> <tr> <th>Rating</th> <th>Typical Distance</th> </tr> </thead> <tbody> <tr> <td>Easy</td> <td>Under 5 miles</td> </tr> </tbody></table>- Save and reload in your browser. The page will look identical — but the structure is now complete.
<thead>groups header rows.<tbody>groups data rows.<tfoot>groups summary or footer rows.- These sections wrap
<tr>elements — they sit between<table>and<tr>. - They do not change default visual appearance, but they improve structure, accessibility, and CSS targeting.
- Write
<tbody>explicitly even though browsers insert it automatically.