thead / tbody / tfoot
<thead>、<tbody>、<tfoot> 用于将表格内容按逻辑分组:表头区域、数据区域和表尾区域。本节将介绍这三个分组的用法、打印分页中的特殊作用以及固定表头的实现。
前置知识
阅读本节前,建议先了解:colgroup 与 col
基础概念
HTML 表格支持三个结构分组元素:<thead>(表头)、<tbody>(表体)和 <tfoot>(表尾)。这三个元素将表格的内容按功能划分为不同区域,使表格结构更加清晰。
这三个分组不仅仅是语义上的——它们在打印分页时特别有用:<thead> 会在每一页重复打印,<tfoot> 会在每页底部打印汇总信息。
语法
基本语法
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>表格分组</title>
<style>
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #ddd;
padding: 10px;
text-align: center;
}
thead th { background: #4285f4; color: #fff; }
tbody td { background: #fff; }
tfoot td { background: #f5f5f5; font-weight: bold; }
</style>
</head>
<body>
<h1>thead / tbody / tfoot</h1>
<table>
<!-- thead:表头 -->
<thead>
<tr>
<th>月份</th>
<th>收入</th>
<th>支出</th>
<th>利润</th>
</tr>
</thead>
<!-- tbody:数据区域(可以有多个 tbody) -->
<tbody>
<tr>
<td>1 月</td>
<td>50,000</td>
<td>35,000</td>
<td>15,000</td>
</tr>
<tr>
<td>2 月</td>
<td>55,000</td>
<td>38,000</td>
<td>17,000</td>
</tr>
<tr>
<td>3 月</td>
<td>60,000</td>
<td>40,000</td>
<td>20,000</td>
</tr>
</tbody>
<!-- tfoot:汇总/表尾 -->
<tfoot>
<tr>
<td>合计</td>
<td>165,000</td>
<td>113,000</td>
<td>52,000</td>
</tr>
</tfoot>
</table>
</body>
</html>详细说明
分组元素的作用
| 元素 | 作用 | 内容类型 |
|---|---|---|
<thead> | 表头区域 | 列标题 |
<tbody> | 数据区域 | 数据行(可多个) |
<tfoot> | 表尾区域 | 汇总行 |
多个 tbody 的用法
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>多个 tbody</title>
<style>
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid #ddd; padding: 10px; text-align: center; }
thead th { background: #333; color: #fff; }
tbody td { background: #fff; }
/* 不同 tbody 之间可以有间距 */
tbody + tbody { border-top: 3px solid #333; }
</style>
</head>
<body>
<h1>多个 tbody 分组</h1>
<table>
<thead>
<tr>
<th>城市</th>
<th>人口(万)</th>
<th>GDP(亿)</th>
</tr>
</thead>
<!-- 第一个 tbody:华北地区 -->
<tbody>
<tr>
<th scope="rowgroup" colspan="3" style="background: #e3f2fd; text-align: left; padding: 8px;">
华北地区
</th>
</tr>
<tr><td>北京</td><td>2189</td><td>41610</td></tr>
<tr><td>天津</td><td>1387</td><td>15695</td></tr>
</tbody>
<!-- 第二个 tbody:华东地区 -->
<tbody>
<tr>
<th scope="rowgroup" colspan="3" style="background: #e8f5e9; text-align: left; padding: 8px;">
华东地区
</th>
</tr>
<tr><td>上海</td><td>2487</td><td>44652</td></tr>
<tr><td>杭州</td><td>1237</td><td>18109</td></tr>
</tbody>
<tfoot>
<tr>
<td>总计</td>
<td>7300</td>
<td>120066</td>
</tr>
</tfoot>
</table>
</body>
</html>打印分页中的特殊作用
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>打印分页</title>
<style>
@media print {
/* thead 在每页顶部重复 */
thead { display: table-header-group; }
/* tfoot 在每页底部重复 */
tfoot { display: table-footer-group; }
/* 表格行不被拆分到两页 */
tr { page-break-inside: avoid; }
}
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: center; }
thead th { background: #333; color: #fff; }
tfoot td { background: #f5f5f5; font-weight: bold; }
</style>
</head>
<body>
<h1>打印友好表格</h1>
<table>
<thead>
<tr>
<th>序号</th>
<th>项目</th>
<th>负责人</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<!-- 假设有 100 行数据,打印时会分多页 -->
<tr><td>1</td><td>项目 A</td><td>张三</td><td>进行中</td></tr>
<tr><td>2</td><td>项目 B</td><td>李四</td><td>已完成</td></tr>
<tr><td>3</td><td>项目 C</td><td>王五</td><td>待开始</td></tr>
</tbody>
<tfoot>
<tr>
<td colspan="4">共 3 个项目</td>
</tr>
</tfoot>
</table>
<p>打印此页面时,thead 会在每页重复,tfoot 会在每页底部显示。</p>
</body>
</html>固定表头(CSS 方案)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>固定表头</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.table-wrapper {
max-height: 300px;
overflow-y: auto;
border: 1px solid #ddd;
border-radius: 8px;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 10px 14px;
text-align: left;
border-bottom: 1px solid #eee;
}
/* 固定表头 */
thead th {
position: sticky;
top: 0;
background: #4285f4;
color: #fff;
z-index: 1;
}
</style>
</head>
<body>
<h1>固定表头</h1>
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>姓名</th>
<th>部门</th>
<th>职位</th>
<th>入职日期</th>
</tr>
</thead>
<tbody>
<tr><td>张三</td><td>技术部</td><td>前端工程师</td><td>2022-03</td></tr>
<tr><td>李四</td><td>产品部</td><td>产品经理</td><td>2021-08</td></tr>
<tr><td>王五</td><td>设计部</td><td>UI 设计师</td><td>2023-01</td></tr>
<tr><td>赵六</td><td>技术部</td><td>后端工程师</td><td>2022-06</td></tr>
<tr><td>孙七</td><td>市场部</td><td>运营专员</td><td>2023-04</td></tr>
<tr><td>周八</td><td>技术部</td><td>全栈工程师</td><td>2021-12</td></tr>
<tr><td>吴九</td><td>人事部</td><td>HR 经理</td><td>2020-09</td></tr>
<tr><td>郑十</td><td>财务部</td><td>会计</td><td>2022-11</td></tr>
</tbody>
</table>
</div>
</body>
</html>实战示例
财务报表
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>财务报表</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
table { width: 100%; border-collapse: collapse; }
caption {
caption-side: top;
text-align: left;
font-size: 20px;
font-weight: bold;
padding-bottom: 16px;
}
th, td { padding: 12px; text-align: right; border-bottom: 1px solid #eee; }
th { background: #1a1a2e; color: #fff; text-align: center; }
td:first-child { text-align: left; font-weight: 600; }
tfoot td { background: #f5f5f5; font-weight: bold; border-top: 2px solid #333; }
</style>
</head>
<body>
<table>
<caption>2024 年度财务报表(单位:万元)</caption>
<thead>
<tr>
<th>项目</th>
<th>Q1</th>
<th>Q2</th>
<th>Q3</th>
<th>Q4</th>
<th>全年</th>
</tr>
</thead>
<tbody>
<tr><td>营业收入</td><td>1,200</td><td>1,350</td><td>1,500</td><td>1,680</td><td>5,730</td></tr>
<tr><td>营业成本</td><td>720</td><td>810</td><td>900</td><td>1,008</td><td>3,438</td></tr>
<tr><td>毛利润</td><td>480</td><td>540</td><td>600</td><td>672</td><td>2,292</td></tr>
<tr><td>运营费用</td><td>200</td><td>220</td><td>240</td><td>260</td><td>920</td></tr>
</tbody>
<tfoot>
<tr><td>净利润</td><td>280</td><td>320</td><td>360</td><td>412</td><td>1,372</td></tr>
</tfoot>
</table>
</body>
</html>注意事项
<tfoot>在 HTML 源码中可以写在<tbody>之前,浏览器会正确渲染- 每个
<table>最多只能有一个<thead>和<tfoot> <tbody>可以有多个,用于数据分组- 固定表头需要
position: sticky+overflow-y: auto的容器 - 打印分页中
thead和tfoot的重复行为取决于浏览器实现
最佳实践
- 始终使用
<thead>包裹表头行 - 使用
<tbody>包裹数据行 - 使用
<tfoot>包裹汇总行 - 长表格使用
position: sticky固定表头 - 打印场景利用
<thead>/<tfoot>的分页重复特性
下一节
继续学习:合并单元格