表格

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

在本节中,我们将讨论构成表格的所有元素,以及在呈现表格数据时应考虑的一些无障碍功能和可用性功能。虽然“学习 HTML”并非主要关于 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: collapse,则 border-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 完成的!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 设置列的宽度。

<col> 样式将对列进行样式设置,只要没有 <td><th> 样式覆盖该样式设置即可。例如,当 <colspan> 用于合并表格某些行(但并非所有行)中的单元格时,您无法确定选择器(例如 tr > *:nth-child(8),它选择每行的第 8 个子元素)将完全突出显示第 8 列,还是将突出显示几行的第 8 列,但会散布一些第 9 列和第 10 列单元格,具体取决于合并了哪些行或列单元格。

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

Layered rendering of the elements used to design HTML tables.

如果 <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>。如果您想使用演示软件(如 Keynote 或 Powerpoint)中提供的功能,您可能需要描述列表

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

许多开发者使用表格来布局表单,但没有必要这样做。但您确实需要了解 HTML 表单,因此我们将在接下来介绍。

检查您的理解情况

测试您对表格的知识。

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

<th>
<caption>
<header>

哪些信息可能适合使用表格进行布局?

一份详细说明学生及其 3 个学期成绩的电子表格信息。
一些科学术语及其描述。
食谱的成分。