<thead> / <tbody> / <tfoot> / <caption>
| Since: | HTML 4(1997) |
|---|
The <thead>, <tbody>, and <tfoot> elements group table rows into a header, body, and footer, respectively. The <caption> element adds a title to a table.
Syntax
<table>
<caption>Table Title</caption>
<thead>
<tr><th>Heading 1</th><th>Heading 2</th></tr>
</thead>
<tbody>
<tr><td>Data 1</td><td>Data 2</td></tr>
</tbody>
<tfoot>
<tr><td>Total</td><td>100</td></tr>
</tfoot>
</table>
Tag List
| Tag | Description |
|---|---|
| <caption> | Specifies a title or heading for the table. Must be the first child element of <table>. |
| <thead> | Represents the header row group of a table. Place rows containing column headings here. |
| <tbody> | Represents the body (data rows) group of a table. Place the actual data rows here. Multiple <tbody> elements are allowed. |
| <tfoot> | Represents the footer row group of a table. Place totals, notes, or summaries here. |
Sample Code
sample_thead_tbody_tfoot_caption.html
<!-- Using all of thead, tbody, tfoot, and caption -->
<table border="1">
<!-- Table title -->
<caption>2024 Monthly Sales</caption>
<!-- Header row group -->
<thead>
<tr>
<th scope="col">Month</th>
<th scope="col">Sales ($k)</th>
<th scope="col">MoM Change</th>
</tr>
</thead>
<!-- Data row group -->
<tbody>
<tr>
<td>Jan</td>
<td>120</td>
<td>+5%</td>
</tr>
<tr>
<td>Feb</td>
<td>98</td>
<td>-18%</td>
</tr>
<tr>
<td>Mar</td>
<td>145</td>
<td>+48%</td>
</tr>
</tbody>
<!-- Footer row group (totals, etc.) -->
<tfoot>
<tr>
<td>Total</td>
<td>363</td>
<td>—</td>
</tr>
</tfoot>
</table>
<!-- Practical example: styling thead and tfoot with CSS -->
<style>
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
thead { background-color: #4a90e2; color: white; }
tfoot { background-color: #f0f0f0; font-weight: bold; }
caption { font-weight: bold; margin-bottom: 8px; text-align: left; }
</style>
<table>
<caption>Inventory List</caption>
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Unit Price</th>
<th scope="col">Stock</th>
</tr>
</thead>
<tbody>
<tr><td>Laptop</td><td>$980</td><td>15</td></tr>
<tr><td>Mouse</td><td>$25</td><td>80</td></tr>
<tr><td>Keyboard</td><td>$58</td><td>40</td></tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Total stock</td>
<td>135</td>
</tr>
</tfoot>
</table>
Result
A table with the caption "2024 Monthly Sales" is displayed. The structure consists of a header row, three data rows, and a total footer row. When printed across multiple pages, some browsers repeat the header and footer on each page.
Notes
Using <thead>, <tbody>, and <tfoot> makes the table structure explicit, which improves compatibility with screen readers and makes CSS styling easier. According to the HTML specification, <tfoot> may appear before <tbody> (immediately after <thead>), but the rendered order is always body then footer. Modern browsers render correctly regardless of source order, but placing <tfoot> at the end is the common convention for readability.
<caption> provides a brief description of the table's content and is recommended for accessibility. By default it appears centered above the table, but you can move it below using the CSS caption-side property.
For the basic table structure (<table>, <tr>, <td>, <th>), see 'table / tr / td / th'.
CSS Styling
<thead>, <tbody>, and <tfoot> make it easy to apply different styles to each section of a table.
/* Sticky header for scrollable tables */
.scrollable-table {
display: block;
max-height: 300px; /* maximum table height */
overflow-y: auto; /* enable vertical scrolling */
}
.scrollable-table thead {
position: sticky;
top: 0;
z-index: 1;
}
/* thead background color */
thead {
background-color: #4488ff;
color: white;
}
thead th {
font-weight: bold;
padding: 0.75em 1em;
}
/* tbody row striping */
tbody tr:nth-child(even) {
background-color: #f5f5f5;
}
tbody tr:hover {
background-color: #e8f0ff;
}
/* tfoot styling (for totals etc.) */
tfoot {
background-color: #eeeeee;
font-weight: bold;
}
/* caption styling */
caption {
caption-side: top; /* top (default) or bottom */
font-weight: bold;
color: #444;
padding: 0.5em 0;
}
Common Mistakes
Mistake 1: Writing tfoot before tbody
While the HTML specification allows tfoot to appear immediately after thead (before tbody), some browsers may have rendering issues with this order. For readability and consistency, placing tfoot at the end is the common practice.
<!-- NG: tfoot before tbody (valid per spec but confusing) --> <table> <thead><tr><th>Item</th><th>Price</th></tr></thead> <tfoot><tr><td>Total</td><td>$50</td></tr></tfoot> <tbody><tr><td>Item A</td><td>$30</td></tr></tbody> </table>
The corrected version looks like this:
<!-- OK: thead → tbody → tfoot order --> <table> <thead><tr><th>Item</th><th>Price</th></tr></thead> <tbody><tr><td>Item A</td><td>$30</td></tr></tbody> <tfoot><tr><td>Total</td><td>$50</td></tr></tfoot> </table>
Mistake 2: Omitting thead/tbody
HTML parsers implicitly add tbody, but omitting it explicitly can cause issues with JavaScript DOM manipulation and JavaScript sorting libraries. Explicit use also makes CSS section-specific styling easier.
<!-- NG: omitting thead/tbody --> <table> <tr><th>Name</th><th>Score</th></tr> <tr><td>Terry Bogard</td><td>980</td></tr> </table>
The corrected version looks like this:
<!-- OK: write thead/tbody explicitly -->
<table>
<thead>
<tr><th>Name</th><th>Score</th></tr>
</thead>
<tbody>
<tr><td>Terry Bogard</td><td>980</td></tr>
</tbody>
</table>
Browser Compatibility
1 and later ○
1 and later ○
1 and later ○
8 ○
7 ○
6 ○
12.1 and later ○
11.1 and earlier ×
1 and later ○
Android Browser
4.4 and later ○
4 and earlier ×* Version data based on MDN.
If you find any errors or copyright issues, please contact us.