Skip to content

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 的容器
  • 打印分页中 theadtfoot 的重复行为取决于浏览器实现

最佳实践

  • 始终使用 <thead> 包裹表头行
  • 使用 <tbody> 包裹数据行
  • 使用 <tfoot> 包裹汇总行
  • 长表格使用 position: sticky 固定表头
  • 打印场景利用 <thead>/<tfoot> 的分页重复特性

下一节

继续学习:合并单元格

参考链接