HTML 表格以行和列的形式显示表格数据。您应根据所展示的内容以及用户对该内容的需求来选择使用哪种 <table>。如果需要呈现、比较、排序、计算或交叉引用数据,那么 <table> 可能是正确的选择。如果您想整理非表格内容(例如大量缩略图),则不适合使用表格。您可以创建图片列表,并使用 CSS 设置网格的样式

在本部分中,我们将讨论构成表格的所有元素,以及在呈现表格数据时需要考虑的一些无障碍功能和易用性功能。虽然“学习 HTML”课程的重点不是 CSS,但我们会介绍一些特定于表格的 CSS 属性。如需详细了解 CSS,请参阅学习 CSS

表格元素(按顺序)

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

<table> 中,您会找到表格标题 (<thead>)、表格正文 (<tbody>) 和可选的表格页脚 (<tfoot>)。这些元素均由表格行 (<tr>) 组成。行包含表格标题 (<th>) 和表格数据 (<td>) 单元格,而这些单元格又包含所有数据。 在 DOM 中,在此之前,您可能会看到两个额外的功能:表格标题 (<caption>) 和列组 (<colgroup>)。根据 <colgroup> 是否具有 span 属性,它可能包含嵌套的表格列 (<col>) 元素。

表格的子级按顺序为:

  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> 上提供的已弃用的属性。

当时有用于在单元格之间和单元格内添加内边距、设置边框和文本对齐方式的属性。用于定义单元格内容与其边框之间以及相邻单元格边框之间的间距的 cellpadding 和 cellspacing 应分别使用 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 单元格有两个标题:Year 和 Lou Minious。此关联表示“1956 年”是“Lou Minious”的毕业“年份”。在此示例中,由于我们可以看到整个表格,因此关联关系一目了然。 即使标题列或行已滚动出视图,使用 <th> 也能提供关联。我们可以明确设置 <th scope="col">Year</th><th scope="row">Lou Minious</th>,但对于这样的表格,枚举的默认值是可行的。 scope 的其他值包括 rowgroupcolgroup,这些值在处理复杂表格时非常有用。

合并单元格

与 MS Excel、Google 表格和 Numbers 类似,您也可以将多个单元格合并为一个单元格。您可以使用 HTML colspanrowspan 属性来完成此操作:

  • 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> 样式。在 CodePen 中,我们将 colspan 设置为合并表格的部分行,而不是全部行。如果 nth-child CSS 选择器应用于 <tr>,则根据合并的行或列,这可能会影响样式。

在这种情况下,`tr > *:nth-child(2)` 会影响每行的第二个子元素。此结果是否符合您的预期?

遗憾的是,仅支持少数属性。样式不会继承到单元格中,而使用 <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 display 属性,请添加 ARIA role 属性。虽然这听起来可能有些多余,但 CSS display 属性可能会影响某些浏览器中的可访问性树。

呈现数据

表格元素具有语义含义,辅助技术会使用这些含义来帮助用户浏览行和列,而不会迷失方向。<table> 元素不应用于演示。如果您需要在列表上方添加标题,请使用标题列表。如果您想以多列布局内容,请使用多列布局。如果您想以网格形式布局内容,请使用 CSS 网格

仅使用表格展示数据。

您可以这样考虑:如果您的数据需要使用电子表格才能在会议上展示,请使用 <table>。如果您想使用演示软件(例如 Google 幻灯片或 PowerPoint)中提供的功能,可能需要说明列表

简而言之:如果您不展示表格数据,请勿使用 <table>。 如果您使用表格进行演示,请设置 role="none"

许多开发者使用表格来布局表单,但这是不必要的。您需要了解 HTML 表单

检验您的掌握情况

测试您对表格相关知识的掌握情况。

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

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

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

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