HTML 表格用于显示包含行和列的表格数据。是否使用 <table> 应根据您要呈现的内容以及用户对该内容的需求来决定。如果要呈现、比较、排序、计算或交叉引用数据,<table> 可能是正确的选择。如果您只是想整齐地排列非表格内容(例如大量缩略图),则不适合使用表格:您可以改为创建图片列表,并使用 CSS 设置网格的样式。

在本部分中,我们将讨论构成表格的所有元素,以及您在呈现表格数据时应考虑的一些无障碍功能和易用性功能。虽然“学习 HTML”课程主要讲解 HTML,并且我们还有一整门课程专门介绍 CSS,但我们还是会介绍一些专门针对表格的 CSS 属性。

表格元素(按顺序)

<table> 标记用于封装表格内容,包括所有表格元素。<table> 的隐式 ARIA 角色为 table;辅助技术知道此元素是一个表格结构,其中包含以行和列排列的数据。如果表格会保持选择状态、具有二维导航或允许用户重新排列单元格顺序,请设置 role="grid"。如果 grid 的行可以展开和收起,请改用 role="treegrid"

<table> 中,您会看到表格标题 (<thead>)、表格正文 (<tbody>) 和(可选)表格页脚 (<tfoot>)。每种内容都由表格行 (<tr>) 组成。行包含表格标题 (<th>) 和表格数据 (<td>) 单元格,这些单元格反过来包含所有数据。在 DOM 中,您可能会在上述任何内容之前找到另外两个功能:表格标题 (<caption>) 和列组 (<colgroup>)。<colgroup> 可能包含嵌套表格列 (<col>) 元素,具体取决于 <colgroup> 是否具有 span 属性。

表格的子项按顺序如下:

  1. <caption> 元素
  2. <colgroup> 元素
  3. <thead> 元素
  4. <tbody> 元素
  5. <tfoot> 元素

我们将介绍 <table> 元素的子元素(这些子元素都是可选的,但建议添加),然后再介绍行、表格标题单元格和表格数据单元格。最后介绍 <colgroup>

表格标题

作为原生语义元素,<caption> 是为表命名的首选方法。<caption> 提供可通过程序关联的描述性表格标题。默认情况下,此类别对所有用户可见且可用。

<caption> 元素应是嵌套在 <table> 元素中的第一个元素。添加标题后,所有用户都可以立即了解表格的用途,而无需阅读周围的文字。或者,您也可以在 <table> 上使用 aria-labelaria-labelledby 提供可访问的名称作为字幕。<caption> 元素没有特定于元素的属性。

标题会显示在表格外面。您可以使用 CSS caption-side 属性设置字幕的位置,这比使用已废弃的 align 属性更为妥当。这样可以将字幕设置为顶部和底部。尚不完全支持使用 inline-startinline-end 进行左侧和右侧定位。顶部是默认的浏览器呈现方式。

最好是数据表应具有清晰的标题和标题注释,并且足够简单,几乎不需要说明。请注意,并非所有用户都有相同的认知能力。如果表格是为了“说明某个要点”或需要其他解释,请简要概述表格的主要要点或用途。摘要的位置取决于其长度和复杂程度。如果简短,请将其用作字幕的内部文本。如果标题较长,请在标题中进行总结,并在表格前面的段落中提供摘要,并使用 aria-describedby 属性将这两者相关联。将表格放在 <figure> 中,并将摘要放在 <figcaption> 中,也是另一种方法。

数据分区

表格的内容最多由三个部分组成:零个或多个表格标题 (<thead>)、表格正文 (<tbody>) 和表格页脚 (<tfoot>)。所有这些部分都是可选的,并且每个部分支持零个或多个。

这些元素对表格的无障碍功能没有帮助,也不会妨碍无障碍功能,但在易用性方面很有用。它们提供样式钩子。例如,标题内容可以固定,而 <tbody> 内容可以滚动。未嵌套在上述三个包含元素中的行会被隐式封装在 <tbody> 中。这三个角色共享相同的隐式角色 rowgroup。这三个元素都没有任何特定于元素的属性。

目前的进展:

<table>
  <caption>MLW Students</caption>
  <thead></thead>
  <tbody></tbody>
  <tfoot></tfoot>
</table>

出于无障碍设计方面的考虑,<tfoot> 元素最初被指定为紧随 <thead> 之后,紧在 <tbody> 之前。因此,您可能会在旧版代码库中看到这种不直观的源代码顺序。

表格内容

表格可以分为表格标题、正文和页脚,但如果表格不包含表格行、单元格和内容,则这些部分都不会起到任何作用。每个表格行 <tr> 包含一个或多个单元格。如果单元格是标题单元格,请使用 <th>。否则,请使用 <td>

用户代理样式表通常会以居中和粗体形式显示 <th> 表格标题单元格中的内容。最好使用 CSS 控制这些默认样式和所有样式,而不是使用以前可用于单个单元格、行甚至 <table> 的已废弃属性。

这些属性可用于在单元格之间和单元格内添加内边距、设置边框以及对齐文本。单元格内边距和单元格间距用于定义单元格内容与其边框之间的距离,以及相邻单元格边框之间的距离,应分别使用 CSS border-collapseborder-spacing 属性进行设置。如果设置了 border-collapse: collapseBorder-spacing 将不会产生任何影响。如果设置了 border-collapse: separate;,则可以使用 empty-cells: hide; 完全隐藏空单元格。如需详细了解如何设置表格样式,请参阅以下有关表格相关 CSS 样式的交互式幻灯片。

在示例中,我们使用 CSS 为表格和每个单元格添加了边框,以使某些功能更显眼:

在本示例中,我们有标题、表格标题和表格正文。标题包含一行,其中包含三个标题 <th> 单元格,从而创建了三列。正文包含三行数据:第一单元格是该行的标题单元格,因此我们使用 <th> 而非 <td>

<th> 单元格具有语义含义,具有隐式 ARIA 角色 columnheaderrowheader。它会将单元格定义为表格单元格的列或行的标题,具体取决于枚举的 scope 属性的值。如果未明确设置 scope,浏览器将默认设置为 colrow。由于我们使用了语义标记,因此 1956 单元格有两个标题:年份和 Lou Minious。从这个关联中,我们可以得知“1956”是“Lou Minious”的毕业“年份”。在此示例中,由于我们可以看到整个表格,因此关联在视觉上是显而易见的。使用 <th> 可提供关联,即使标题列或行已滚动到视野之外也是如此。我们可以明确设置 <th scope="col">Year</th><th scope="row">Lou Minious</th>,但对于这样简单的表格,枚举的默认值也适用。scope 的其他值包括 rowgroupcolgroup,适用于复杂表格。

合并单元格

与 MS Excel、Google 表格和 Numbers 类似,您可以将多个单元格合并到单个单元格中。这可以通过 HTML 实现! colspan 属性用于合并单个行中的两个或多个相邻单元格。rowspan 属性用于合并跨行单元格,并放置在顶行单元格上。

在此示例中,表格标题包含两行。第一个标题行包含跨四列的三个单元格:中间单元格包含 colspan="2"。这会合并两个相邻的单元格。第一个和最后一个单元格包含 rowspan="2"。这会将该单元格与相邻行中紧挨其下的单元格合并。

表格标题中的第二行包含两个单元格;这些单元格是第二行中第二列和第三列的单元格。 由于第一行中第一列和最后一列中的单元格跨越两行,因此未为第一列或最后一列声明任何单元格。

如果某个单元格由多个标题单元格定义,并且关联无法仅通过 scope 属性设置,请添加 headers 属性,并附上以空格分隔的关联标题列表。由于此示例的表格较为复杂,因此我们使用 scope 属性明确定义了标题的范围。为了更清楚地说明,我们为每个单元格添加了 headers 属性。

在这种简单的用例中,headers 属性可能不是必需的,但随着表的复杂性增加,将它们添加到您的工具箱中非常重要。结构复杂的表格(例如,合并了标题或单元格或具有两个以上列级或行级标题的表格)需要明确标识关联的标题单元格。在这种复杂的表格中,请将每个数据单元格与每个对应的标题单元格显式关联,并将所有关联标题的 id 值(以空格分隔)列表作为 headers 属性的值。

headers 属性更常见于 <td> 元素,但在 <th> 上也有效。

不过,复杂的表格结构可能不易被所有用户(而不仅仅是屏幕阅读器用户)理解。从认知角度和屏幕阅读器支持方面来看,表格越简单(跨列单元格越少或没有跨列单元格,即使不添加范围和标题),就越容易理解。而且更易于管理!

设置表格样式

我们之前曾简要提及过两个相对不太常见的元素:列组 <colgroup> 元素及其唯一的后代,即空的 <col> 列元素。<colgroup> 元素用于在表格中定义列组(即 <col> 元素)。

如果使用,列分组应嵌套在 <table> 中,紧跟 <caption> 并位于所有表格数据之前。如果这些值跨越多列,请使用 span 属性。

表的内容大纲顺序通常如下所示,其中 <table><caption> 是应包含的两个元素:

<table>
  <caption>Table Caption</caption>
  <colgroup>
    <col/>
  </colgroup>
  <thead>...

从帮助提高表格易用性方面来看,<colgroup><col> 没有语义意义,但它们确实支持有限的列样式设置,包括使用 CSS 为列设置宽度。

只要没有 <td><th> 样式替换该样式,<col> 样式就会为列设置样式。例如,如果 <colspan> 用于合并表格中部分行(而非所有行)中的单元格,您无法确定 tr > *:nth-child(8) 等选择器(用于选择每行的第 8 个子元素)会突出显示第 8 列的全部内容,还是会突出显示多行中的第 8 列,但其中包含第 9 列和第 10 列的部分单元格,具体取决于合并了哪些行或列单元格。

遗憾的是,系统仅支持少数属性,样式不会继承到单元格中,并且在定位单元格时使用 <col> 元素的唯一方法是使用包含 :has() 关系选择器的复杂选择器。

用于设计 HTML 表格的元素的分层渲染。

如果 <table><colgroup> 都有背景颜色,则 <colgroup>background-color 将位于顶部。绘制顺序为:表格、列组、列、行组、行,其中单元格位于最后和顶部,如表格层架构所示。<td><th> 元素不是 <colgroup><col> 元素的后代,也不会继承它们的样式。

如需对表格进行条纹处理,CSS 结构选择器非常有用。例如,tbody tr:nth-of-type(odd) {background-color: rgba(0 0 0 / 0.1);} 会在表格正文中的每个奇数行中添加半透明的黑色,以便在 <colgroup> 上设置的任何背景效果都能透过来。

默认情况下,表格不支持自适应。而是默认根据内容的大小进行调整。需要采取额外措施,才能让表格布局样式在各种设备上都能有效运行。如果您要更改表格元素的 CSS 显示属性,请添加 ARIA role 属性。虽然这可能听起来很冗余,但 CSS display 属性可能会影响某些浏览器中的无障碍树。

呈现数据

表格元素具有语义含义,辅助技术会使用这些含义来浏览行和列,而不会迷失方向。<table> 元素不应用于呈现。如果您需要在列表上方显示标题,请使用标题列表。如果您想以多列的形式排列内容,请使用多列布局。如果您想以网格形式排列内容,请使用 CSS 网格。仅使用表格展示数据。这样想:如果您的数据需要以电子表格的形式在会议中展示,请使用 <table>。如果您想使用 Keynote 或 PowerPoint 等演示文稿软件提供的功能,可能需要使用说明列表

如果您不呈现表格数据,请勿使用 <table>。如果您确实要使用表格进行演示,请设置 role="none"

许多开发者使用表格来排列表单,但其实没有必要。不过,您需要了解 HTML 表单,因此我们接下来将介绍该内容。

检查您的理解情况

测试您对表格的知识。

哪个元素用于标记标题单元格?

<header>
请重试。
<caption>
请重试。
<th>
正确!

哪些信息可能适合采用表格布局?

一些科学术语及其说明。
请重试,这更适合 <dl>
一个电子表格,其中详细列出了 3 个学期的学生及其成绩。
正确!
食谱中的食材。
请重试,这更适合 <ul>