Table布局

标准结构

标准结构

css
一个语义化、功能完备的表格,其标准嵌套关系如下:

<table> (容器)
	<caption> (表格标题,必须是第一个子元素)
	<colgroup> (列组,用于统一控制列宽/背景,内部包含 <col>)
	<thead> (表头块)
    <tr> (行)
    	<th> (表头单元格,自带加粗和居中)
	<tbody> (正文块)
    <tr>
      <th> (如果是侧边表头,可以放在这)
      <td> (标准数据单元格)
  <tfoot> (表尾/统计块)
    <tr>
    	<td> (或 <th>)

A. 关于 <th> 的位置

<th> 不仅仅属于 <thead>

  • 如果在 <thead> 里,它代表列标题
  • 如果在 <tbody><tr> 第一个位置,它代表行标题。这对于屏幕阅读器(无障碍访问)非常重要。

B. <colgroup> 的内部

<colgroup> 只是个容器,里面通常需要配合 <col> 标签来发挥作用:

html
<colgroup>
  <col style="background-color: #f0f0f0; width: 100px;"> 
  <col style="width: 200px;">           
</colgroup>
html
<table>
  <caption>2024年季度营收统计</caption>
  <colgroup>
    <col span="1" style="background-color: #eee;"> <col span="2"> </colgroup>
  <thead>
    <tr>
      <th>季度</th>
      <th>收入 (RMB)</th>
      <th>备注</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>第一季度</th> <td>10,000</td>
      <td>开局良好</td>
    </tr>
    <tr>
      <th>第二季度</th>
      <td>12,000</td>
      <td>稳步增长</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td>总计</td>
      <td colspan="2">22,000</td> 
    </tr>
  </tfoot>
</table>

table

table按照这个顺序:

一个可选的 caption 元素 零个或多个的colgroup 元素 一个可选的thead元素

下列任意一个:

  • 零个或多个 tbody
  • 零个或多个 tr

一个可选的tfooter元素

caption

HTML <caption> 元素 (or HTML 表格标题元素) 展示一个表格的标题,它常常作为table的第一个子元素出现,同时显示在表格内容的最前面,但是,它同样可以被 CSS 样式化,所以,它同样可以出现在任何一个一个相对于表格的做任意位置。

以下是与 <caption> 相关的核心 CSS 属性:

1. 位置控制:caption-side

这是 <caption> 最专属的属性。

  • top (默认值):标题显示在表格的正上方。
  • bottom:标题显示在表格的正下方。
  • inline-start / inline-end(实验性/特定浏览器):将标题放置在侧边(逻辑属性)。

2. 对齐方式

由于 <caption> 本身是一个块级元素,且宽度默认与表格对齐,对齐方式通常使用:

  • text-align:控制标题文本在标题区域内的水平位置(left, center, right)。
  • vertical-align:只有在某些特定的旧式浏览器渲染模式下才有用,通常我们直接依靠 caption-side 来决定上下。

colgroup

<colgroup> 元素定义了表格中的一组列。

根据 W3C 规范,你只能在 <col><colgroup> 上设置以下四类属性。其他的(如 font-size, color, text-align)通常会被无视

width:控制列宽。在 table-layout: fixed 模式下,这是定义列宽最标准的方法。

background:设置整列的背景色。这是它的高光时刻,能让你一键实现“斑马纹”或高亮某一列。

border:只有在 border-collapse: collapse 时才有效。

visibility:设置为 collapse 可以隐藏整列。

在 CSS 配合下,HTML 的 span 属性非常强大:

这里的“黑科技”:visibility: collapse

这是 <col> 特有的一个杀手锏:

  • 如果你设置 display: none,表格会重新计算布局,可能会产生抖动。
  • 如果你设置 visibility: collapse,该列会消失,但不会影响表格其他部分的布局高度。这在动态显示/隐藏复杂表格列时非常有用。

在表格布局中,span 属性是 <col> 的灵魂,它决定了你的样式指令能**“横跨”**多少列。

默认情况下,一个 <col> 标签只对应表格中的 1 列

如果你想让多列共享同一个宽度或背景色,而不想写一堆重复的 <col>,就用 span

  • 语法<col span="数字">
  • 逻辑:它告诉浏览器:“接下来的 $N$ 列,都归我管。”

span 只能在 <col><colgroup> 上使用。

thead

HTML 的 <thead> 元素定义了一组定义表格的列头的行。

html
<table>
  <caption>
    Council budget (in £) 2018
  </caption>
  <thead>
    <tr>
      <th scope="col">Items</th>
      <th scope="col">Expenditure</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Donuts</th>
      <td>3,000</td>
    </tr>
    <tr>
      <th scope="row">Stationery</th>
      <td>18,000</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th scope="row">Totals</th>
      <td>21,000</td>
    </tr>
  </tfoot>
</table>

核心 CSS 属性

  • display: table-header-group; 这是 <thead> 的默认 display 值。这个属性告诉浏览器:“无论 HTML 里我被写在哪里,渲染时请把我放在表格的最顶部。”
  • 背景与边框: 你可以给 <thead> 设置 background,它会覆盖整个表头区域。但要注意,border 属性在 <thead> 上通常无效(除非使用 border-collapse: collapse),通常边框是加在内部的 th 上的。
  • vertical-align: 默认通常是 middle。你可以通过设置 thead { vertical-align: bottom; } 让所有表头文字沉到底部。

tbody

<tbody> 元素和它的兄弟节点 和 为出于无障碍访问需求的屏幕或打印机上的表格渲染提供了有用的语义信息。

1. 核心 CSS 属性

  • display: table-row-group; 这是它的默认值。它将内部的行紧密耦合在一起。

  • 独立的滚动条(高级技巧): 这是很多开发者的梦想——固定表头,只让 tbody 滚动。

    注意:这种方法会破坏原生的表格对齐逻辑,需要手动对齐列宽。

2. 斑马纹与交互:伪类选择器

<tbody> 是应用 条纹背景悬停效果 的主战场,这样可以极大地提高长表格的可读性。

  • 斑马纹 (Zebra Striping)
  • 悬停高亮 (Hover State)

3. 分割线处理

border-collapse: collapse; 模式下,<tbody> 本身很难直接设置边框,边框通常表现为单元格之间的重合。

如果你想给整个数据区加一个大边框,通常需要在 <tbody> 内部的第一个和最后一个 td 上做文章,或者给 table 整体加边距。

4. 逻辑属性:empty-cells

如果你的 tbody 中有很多空的数据单元格(比如有些月份没有销售额),你可以利用这个属性控制外观:

  • empty-cells: hide;:空单元格不显示背景和边框,看起来就像那里有个“洞”。
  • empty-cells: show;:即使没内容,也要保持格子整齐。

<tr>

在表格布局中,<tr>(Table Row)是表格的行容器。它就像一根横杆,把一个个单元格(<th><td>)串在一起。

虽然它是一个容器,但它的 CSS 行为非常特殊,甚至有些“倔强”。

1. 核心 CSS 属性

  • display: table-row; 这是默认值。它不像 div 那样是 block。这意味着你不能给 <tr> 设置 margin。如果你想让行与行之间有间距,只能使用 border-spacing(在 table 上设置)或者给 tdpadding
  • 背景设置: 这是 <tr> 最常用的场景。给 <tr> 设置 background,背景会铺满整行所有的单元格。这在做“斑马纹”或“整行高亮”时非常方便。
  • vertical-align: 你可以统一控制整行内所有单元格的对齐方式。

2. 边框陷阱(新手必看)

这是 <tr> 最让人头疼的地方:在默认情况下,你不能直接给 <tr> 加边框。

  • 无效写法tr { border: 1px solid red; }(通常没反应)。
  • 解决方案:你必须在 <table> 上设置 border-collapse: collapse;。只有在这个模式下,给 <tr> 设置的边框才会显示出来。

3. 动态交互::hover

<tr> 是处理用户交互的最佳位置。为了让用户不看错行,我们通常会加一个悬停效果:

4. 隐藏行:visibility: collapse vs display: none

如果你想动态隐藏某一行,这两个值有很大区别:

  • display: none:这一行彻底消失,表格会重新计算布局,下方的行会上移。
  • visibility: collapse:专门为表格设计。行消失了,但它原本占据的高度空间会被保留(或者在某些浏览器中产生类似 display: none 的效果,但在复杂脚本中更稳定)。

表格行元素

  • <tr> 可以作为其 table 父元素的直接子元素,但前提是 <table> 没有 子元素,并且只能位于任何 caption、 和 元素之后。否则,父元素必须是theadtbody或 元素。
  • CSS 伪类 :nth-of-type:first-of-type:last-of-type 通常用于选择所需的行集及其数据和标题单元格(“tdth` 元素)。
tr:nth-of-type(odd) {
  background-color: #eee;
}

tr th[scope="row"] {
  background-color: #d6ecd4;
}

我们添加了额外的表格行(<tr>)作为第一行,其中的列标题单元格(th)为每列提供了一个标题。我们将这一行放在thead分组元素中,以表示这是表格的表头。scope 属性被添加到该页眉行中的每个表头单元格(<th>)中,以明确指定每个表头单元格与其所在列中的所有单元格相关,即使这些单元格位于tbody中。

css
tr:nth-of-type(odd) {
  background-color: #eee;
}

tr th[scope="col"] {
  background-color: #505050;
  color: #fff;
}

tr th[scope="row"] {
  background-color: #d6ecd4;
}

th

1. 默认样式的三大特征

浏览器会给 <th> 预设一套“权威感”十足的样式:

  • font-weight: bold;:默认加粗。
  • text-align: center;:内容默认居中(而 <td> 默认左对齐)。
  • 语义层级:它是为了解释数据而存在的,屏幕阅读器会优先读取 <th> 的内容。

2. 核心属性:scope (HTML 增强)

虽然这是个 HTML 属性,但它决定了 CSS 样式的应用逻辑。你必须明确这个表头是属于还是

  • <th scope="col">:它是这一列的标题(常在 <thead> 中)。
  • <th scope="row">:它是这一行的标题(常在 <tbody> 的每一行开头)。

3. 关键 CSS 控制

A. 垂直对齐 vertical-align

当表头单元格比其他单元格高时(比如某列标题很长),你可以控制它:

B. 文本不换行 white-space

如果你不希望表头因为列宽太窄而自动换行,可以强制它单行显示:


4. 排序状态的样式处理

在现代交互表格中,<th> 经常被点击用来排序。这时我们会用到伪元素:


5. 高级技巧:处理复杂的合并(colspan/rowspan)

当一个表头需要统领多个子列时,colspan 会打破原有的网格:

在 CSS 中,合并后的 th 会自动获得两个单元格的总宽度。如果开启了 table-layout: fixed,合并后的宽度会非常稳定。

HTML <th> 元素定义表格内的表头单元格。这部分特征是由 scopeheaders 属性准确定义的。

  • abbr

    一个简短的描述,作为对表头单元格内容的替代标签,用于在其他上下文中引用该单元格。一些用户代理(如语音阅读器)可能会在内容本身之前呈现此描述。

  • colspan

    一个非负整数值,指示表头单元格跨越或扩展多少列。默认值为 1。用户代理会将大于 1000 的值视为不正确,而默认将其设置为 1。

  • headers

    包含了一个空格分隔的字符串(对应于为此表头单元格提供标题的 <th> 元素的 id 属性)的列表。

  • rowspan

    一个非负整数值,指示表头单元格跨越或扩展多少行。默认值为 1。如果该值被设置为 0,这个单元格就被扩展到 <th> 所属的表格分组部分(、 或 )的最后一个单元。比 65534 大的值被会被裁剪到 65534

  • scope

    定义了表头元素(在 <th> 中定义)关联的单元格。可能的枚举值如下:row:表头关联所属的行中所有的单元格。col:表头关联所属的列中所有的单元格。rowgroup:表头属于一个行组并与其中所有单元格相关联。colgroup:表头属于一个列组并与其中所有单元格相关联。如果未指定 scope 属性,或其值不是 rowcolrowgroupcolgroup,则浏览器会自动选择标题单元格适用的单元格集。

使用说明

  • 只能在 元素内使用 <th>
  • 在简单的上下文中,在表头单元格(<th> 元素)上使用 scope 属性是多余的,因为 scope 会被默认推断。然而,某些辅助技术可能无法正确推断,因此指定标题范围可能会改善用户体验。
  • 当使用 colspanrowspan 属性来使表头单元格跨越多个列和行时,未定义这些属性的单元格(默认为 1)会自动适配表结构中的空闲可用空间,跨越 1x1 单元格,如下图所示:

演示表格单元的列和行跨越的插图:单元格 1、3 和 4 跨越两行;单元格 2 跨越两列;单元格 5 和 6 适配第二行第二列和第三列的可用单元格

属性:

headers包含以空格分隔的字符串列表,每个字符串对应于为此表单元格提供标题的 th 元素的 id 属性。
rowspan跨行
colspan跨列

<td> 只能在 元素中使用。

当使用 colspanrowspan 属性跨多个列和行的数据单元格时,未定义这些属性的单元格(默认值为 1)将自动适应跨 1x1 单元格的表结构中的可用空间,如下图所示:

Illustration demonstrating column and row spanning of table cells: cells 1, 3, and 4 spanning two rows; cell 2 spanning two columns; cells 5 and 6 fitting into the available cells that are the second and third columns in the second row

td

<td>HTML 元素定义包含数据的表的单元格,并可用作tr元素的子元素。

padding:这是控制表格“呼吸感”的最重要手段。

  • 注意: 单元格不支持 margin,如果你想让内容离边框远点,必须用 padding

vertical-align

  • 默认值通常是 inherit(最终表现为 middle)。
  • topmiddlebottom 是三大利器。在多行文本对比中,设置为 top 通常会让表格看起来更整齐。

tfoot

1. 核心 CSS 属性

display: table-footer-group; 这是它的默认值。类似于 <thead>,无论你在 HTML 源码中把 <tfoot> 写在 <tbody> 之前还是之后,浏览器渲染时都会强制将其置于表格的最底部

背景与边框: 通常会给 <tfoot> 设置一个与 <thead> 呼应的深色背景,或者一条明显的顶部粗边框,以示与上方数据的区分。

HTML 元素 <tfoot> 定义了一组表格中各列的汇总行。

内容类别无。
允许的内容0 或多个 元素。
标签省略开始标签是必需的。在父元素 没有后续内容的情况下,结束标签可被省略。
允许的父元素table 元素。注意这是自 HTML5 起有的要求。 注意,这与上述 HTML5 的标准相冲突。

在小空间展示大型表格

网络上表格的一个普遍问题是,当内容量很大时,它们在小屏幕上的原生效果并不好,而且使它们可滚动的方法并不明显,特别是当标记可能来自 CMS,无法添加一个包装器时。

这个例子提供了一种在小空间中显示表格的方法。我们隐藏了 HTML 内容,因为它非常大,而且没有什么特别之处。在这个例子中,研究其 CSS 代码更有用。

当查看这些样式时,你会注意到表格的 display 属性已被设置为 block。虽然允许滚动,但表格失去了一些完整性,而且表格单元格会尽量变小。为了缓解这个问题,我们在 <tbody> 上将 white-space 设置为 nowrap(空白字符不换行)。然而,我们没有对 <thead> 进行设置,以避免长标题迫使列的宽度超过显示数据所需的宽度。

为了在向下滚动时保持表头在页面上,我们在 <th> 元素上将 position 设置为 sticky。注意,我们没有border-collapse 设置为 collapse,因为如果我们这样做,表头就不能与表格的其他部分正确分开。

table,
th,
td {
  border: 1px solid;
}

table {
  width: 100%;
  max-width: 400px;
  height: 240px;
  margin: 0 auto;
  display: block;
  overflow-x: auto;
  border-spacing: 0;
}

tbody {
  white-space: nowrap;
}

th,
td {
  padding: 5px 10px;
  border-top-width: 0;
  border-left-width: 0;
}

th {
  position: sticky;
  top: 0;
  background: #fff;
  vertical-align: bottom;
}

th:last-child,
td:last-child {
  border-right-width: 0;
}

tr:last-child td {
  border-bottom-width: 0;
}

image-20250424160918272

CSS

Gemini said

没错!掌握了 HTML 结构只是搭好了“骨架”,真正的布局魔法全在 CSS 里。

表格的 CSS 逻辑非常特殊,它有一套独立于普通 div 布局的规则(即 Internal Table Objects)。我们要探索的 CSS 核心可以拆解为以下三个关卡:


第一关:边框之战(Border Collapse)

这是每个学习表格的人遇到的第一个坑。默认情况下,表格的单元格边框是分离的。

  • border-collapse: collapse;:这是最常用的属性。它会将相邻单元格的边框合并为一条,让表格看起来清爽。
  • border-spacing: 10px;:只有在 border-collapse: separate; 时才有效,用来控制单元格之间的空隙(类似老式 HTML 的 cellspacing)。

第二关:算法之谜(Table Layout)

这是表格性能和宽度的核心控制开关。

  • table-layout: auto; (默认值)
    • 逻辑:浏览器先扫描整列的内容,根据内容最长的一行来决定列宽。
    • 缺点:内容多时渲染慢,且容易撑破布局。
  • table-layout: fixed; (高手必用)
    • 逻辑:浏览器不看内容,直接根据第一行(或 <col>)定义的宽度来定死。
    • 优点:渲染速度极快,且你可以精准控制每一列的百分比或像素值。如果单元格内容超出了,可以用 overflow: hidden 截断。

第三关:内部对象的特殊对齐

表格内部的元素(th, td)不吃 margin: auto 那一套,它们有自己的规则:

  • vertical-align:在表格单元格里,它是灵魂属性。你可以轻松实现 top, middle, bottom 对齐,而不需要 Flexbox。
  • text-align:控制内容的水平对齐。

第四关:列的批量装修(The <col> power)

虽然你在 HTML 里写了 <colgroup>,但要在 CSS 里利用它,有一些局限性:

  • <col> 上设置 widthbackgroundbordervisibility 是有效的。
  • 但你不能<col> 上设置 colorfont-size。这些属性必须写在真实的 tdth 上。

⚠️ 一个容易被忽略的高级特性:empty-cells

当你有一个单元格里没有任何内容(连个空格都没有)时,你想让它的背景和边框显示出来吗?

  • empty-cells: show; (默认)
  • empty-cells: hide; (如果你想让空单元格直接“隐身”)

评论

评论加载中……