HTML 表格高级功能和可访问性
在本模块的第二篇文章中,我们将介绍 HTML 表格的一些更高级的功能——例如标题/摘要以及将行分组到表头、表体和表尾部分——以及表格对视力障碍用户的无障碍性。
先决条件 | HTML 基础知识(参见 HTML 简介)。 |
---|---|
目标 | 了解更高级的 HTML 表格功能以及表格的无障碍性。 |
使用 <caption> 为表格添加标题
您可以通过将标题放在 <caption>
元素内,并将该元素嵌套在 <table>
元素内,为表格添加标题。您应该将其放在打开的 <table>
标签的正下方。
<table>
<caption>
Dinosaurs in the Jurassic period
</caption>
…
</table>
如您从上面的简短示例中推断的那样,标题旨在包含对表格内容的描述。这对于所有希望快速了解表格是否对他们有用的读者来说很有用,因为他们浏览页面时,但对盲人用户尤其如此。与其让屏幕阅读器读出许多单元格的内容只是为了找出表格的内容,不如让用户依赖标题,然后决定是否更详细地阅读表格。
标题放在 <table>
标签的正下方。
注意:summary
属性也可以在 <table>
元素上使用以提供描述——这也会被屏幕阅读器读出。但是,我们建议使用 <caption>
元素,因为 summary
已弃用,并且视力正常的用户无法阅读(它不会出现在页面上)。
主动学习:添加标题
让我们尝试一下,重新审视我们在上一篇文章中首次遇到的示例。
- 打开您语言老师的学校时间表,该时间表来自 HTML 表格基础 的末尾,或创建我们 timetable-fixed.html 文件的本地副本。
- 为表格添加一个合适的标题。
- 保存您的代码并在浏览器中打开它,以查看它的外观。
注意:您可以在 GitHub 上找到我们的版本——参见 timetable-caption.html (也查看它)。
使用 <thead>、<tbody> 和 <tfoot> 添加结构
随着表格在结构上变得更加复杂,使用 <thead>
、<tbody>
和 <tfoot>
为其提供更多结构定义非常有用,这些元素允许您标记表格的表头、表体和表尾部分。
这些元素不会使表格对屏幕阅读器用户更易访问,也不会独立地导致任何视觉增强。但是,它们对样式和布局非常有用——充当添加 CSS 到表格的有用钩子。为了给您一些有趣的示例,对于长表格,您可以使表格的表头和表尾在每页打印时重复,并且您可以使表格主体显示在一页上,并且内容可通过上下滚动访问。
要使用它们,应按以下顺序包含它们
<thead>
元素必须包含表格的表头部分——这通常是包含列标题的第一行,但这并不总是这样。如果您使用的是<col>
/<colgroup>
元素,则表格标题应放在这些元素的正下方。<tbody>
元素需要包含表格内容的主体部分,而不是表格的表头或表尾。<tfoot>
元素需要包含表格的表尾部分——这可能是一行,其中包含前几行中项目的总和,例如。
注意:<tbody>
始终包含在每个表格中,如果您没有在代码中指定,则隐式包含。要检查这一点,请打开您以前不包含 <tbody>
的示例之一,并在您的 浏览器开发工具 中查看 HTML 代码——您将看到浏览器已为您添加了此标签。您可能会想知道为什么您应该费心包含它——您应该这样做,因为它让您对表格结构和样式有更多控制。
主动学习:添加表格结构
让我们将这些新元素付诸行动。
- 首先,创建一个 spending-record.html 和 minimal-table.css 的本地副本到一个新文件夹中。
- 尝试在浏览器中打开它——您会看到它看起来还可以,但可以改进。包含已支出金额总和的“SUM”行似乎位置不对,代码中还有一些细节缺失。
- 将明显的标题行放在
<thead>
元素中,“SUM”行放在<tfoot>
元素中,其余内容放在<tbody>
元素中。 - 保存并刷新,您将看到添加
<tfoot>
元素已导致“SUM”行向下移到表格底部。 - 接下来,添加一个
colspan
属性,使“SUM”单元格跨越前四列,以便实际数字出现在“Cost”列的底部。 - 让我们为表格添加一些简单的额外样式,以便您了解这些元素对应用 CSS 的作用有多大。在 HTML 文档的头部,您将看到一个空的
<style>
元素。在该元素内,添加以下几行 CSS 代码csstbody { font-size: 95%; font-style: italic; } tfoot { font-weight: bold; }
- 保存并刷新,看看结果。如果没有
<tbody>
和<tfoot>
元素,您将不得不编写更复杂的选择器/规则才能应用相同的样式。
完成后的表格应该看起来像这样
注意:您也可以在 GitHub 上找到它,名称为 spending-record-finished.html。
嵌套表格
只要您包含完整的结构,包括 <table>
元素,就可以将一个表格嵌套在另一个表格中。这通常并不建议这样做,因为它会使标记更令人困惑,并且对屏幕阅读器用户更难以访问,并且在许多情况下,您也可以简单地在现有表格中插入额外的单元格/行/列。但是,有时这是必要的,例如,如果您想轻松地从其他来源导入内容。
以下标记显示了一个简单的嵌套表格
<table id="table1">
<tr>
<th>title1</th>
<th>title2</th>
<th>title3</th>
</tr>
<tr>
<td id="nested">
<table id="table2">
<tr>
<td>cell1</td>
<td>cell2</td>
<td>cell3</td>
</tr>
</table>
</td>
<td>cell2</td>
<td>cell3</td>
</tr>
<tr>
<td>cell4</td>
<td>cell5</td>
<td>cell6</td>
</tr>
</table>
其输出看起来像这样
面向视障用户的表格
让我们简要回顾一下我们如何使用数据表格。表格是一个方便的工具,可以让我们快速访问数据,并让我们查找不同的值。例如,只需快速浏览下面的表格,就可以找到 2016 年 8 月在根特销售了多少枚戒指。为了理解它的信息,我们在这个表格中的数据与其列和/或行标题之间建立了视觉联系。
衣服 | 配饰 | |||||
---|---|---|---|---|---|---|
裤子 | 裙子 | 连衣裙 | 手镯 | 戒指 | ||
比利时 | 安特卫普 | 56 | 22 | 43 | 72 | 23 |
根特 | 46 | 18 | 50 | 61 | 15 | |
布鲁塞尔 | 51 | 27 | 38 | 69 | 28 | |
荷兰 | 阿姆斯特丹 | 89 | 34 | 69 | 85 | 38 |
乌特勒支 | 80 | 12 | 43 | 36 | 19 |
但是,如果您无法建立这些视觉联系呢?那么您如何阅读上面的表格呢?视力障碍者通常使用屏幕阅读器,屏幕阅读器会向他们朗读网页上的信息。当您阅读纯文本时,这没问题,但解释表格对盲人来说可能是一个不小的挑战。然而,通过适当的标记,我们可以用编程的联系来代替视觉的联系。
注意:根据 2017 年 WHO 数据,大约有 2.53 亿人患有视力障碍。
本文的这一部分提供了使表格尽可能无障碍的其他技术。
使用列标题和行标题
屏幕阅读器将识别所有标题,并使用它们在这些标题与其相关的单元格之间建立编程的联系。列标题和行标题的组合将识别和解释每个单元格中的数据,以便屏幕阅读器用户可以像视力正常的用户一样解释表格。
我们已经在上一篇文章中介绍了标题——参见 使用 <th> 元素添加标题。
scope 属性
本文的一个新主题是 scope
属性,该属性可以添加到 <th>
元素中,以告知屏幕阅读器标题究竟是哪个单元格的标题——例如,它是其所在行的标题,还是列的标题?回顾我们前面提到的支出记录示例,您可以明确地将列标题定义为列标题,如下所示
<thead>
<tr>
<th scope="col">Purchase</th>
<th scope="col">Location</th>
<th scope="col">Date</th>
<th scope="col">Evaluation</th>
<th scope="col">Cost (€)</th>
</tr>
</thead>
并且每行都可以像这样定义标题(如果我们添加了行标题以及列标题)
<tr>
<th scope="row">Haircut</th>
<td>Hairdresser</td>
<td>12/09</td>
<td>Great idea</td>
<td>30</td>
</tr>
屏幕阅读器将识别像这样结构化的标记,并允许其用户一次读出整列或整行,例如。
scope
还有两个可能的取值——colgroup
和 rowgroup
。这些用于位于多个列或行之上的标题。如果您回头看看本文开头部分的“2016 年 8 月销售的商品”表格,您将看到“衣服”单元格位于“裤子”、“裙子”和“连衣裙”单元格的正上方。所有这些单元格都应标记为标题 (<th>
),但“衣服”是一个位于顶部的标题,它定义了其他三个子标题。“衣服”因此应获得 scope="colgroup"
属性,而其他则应获得 scope="col"
属性
<thead>
<tr>
<th colspan="3" scope="colgroup">Clothes</th>
</tr>
<tr>
<th scope="col">Trousers</th>
<th scope="col">Skirts</th>
<th scope="col">Dresses</th>
</tr>
</thead>
相同规则也适用于多个分组行的标题。再次查看“2016 年 8 月销售的商品”表格,这次重点关注带有“阿姆斯特丹”和“乌特勒支”标题 (<th>
) 的行。您会注意到,“荷兰”标题(也标记为 <th>
元素)跨越两行,是另外两个子标题的标题。因此,应在此标题单元格上指定 scope="rowgroup"
,以帮助屏幕阅读器建立正确的关联
<tr>
<th rowspan="2" scope="rowgroup">The Netherlands</th>
<th scope="row">Amsterdam</th>
<td>89</td>
<td>34</td>
<td>69</td>
</tr>
<tr>
<th scope="row">Utrecht</th>
<td>80</td>
<td>12</td>
<td>43</td>
</tr>
id 和 headers 属性
使用 id
和 headers
属性来建立标题和单元格之间的关联,是使用 scope
属性的另一种方法。
headers
属性接受一个无序的、用空格分隔的 字符串 列表,每个字符串对应一个提供数据单元格 (<td>
元素) 或另一个标题单元格 (<th>
元素) 的标题的 <th>
元素的唯一 id
。
这使您的 HTML 表格对表格中每个单元格的位置有了明确的定义,该位置由每个单元格所属的列和行的标题定义,有点像电子表格。为了使其正常工作,表格确实需要列标题和行标题。
回到我们的“2016 年 8 月销售的商品”示例,我们可以像这样使用 id
和 headers
属性
- 在表格的每个
<th>
元素中添加一个唯一的id
。 - 在每个充当副标题的
<th>
元素中添加一个headers
属性,例如,具有上方的标题元素。该值是位于顶部的标题的id
,它定义了副标题,在本例中,对于列标题是"clothes"
,对于行标题是"belgium"
。 - 在每个
<td>
元素中添加headers
属性,并添加相关<th>
元素的id
,以空格分隔的列表形式。你可以像在电子表格中那样进行操作:找到数据单元格,并搜索相应的行和列标题。指定id
的顺序无关紧要,但应该保持一致以保持组织。
<thead>
<tr>
<th id="clothes" colspan="3">Clothes</th>
</tr>
<tr>
<th id="trousers" headers="clothes">Trousers</th>
<th id="skirts" headers="clothes">Skirts</th>
<th id="dresses" headers="clothes">Dresses</th>
</tr>
</thead>
<tbody>
<tr>
<th id="belgium" rowspan="3">Belgium</th>
<th id="antwerp" headers="belgium">Antwerp</th>
<td headers="antwerp belgium clothes trousers">56</td>
<td headers="antwerp belgium clothes skirts">22</td>
<td headers="antwerp belgium clothes dresses">43</td>
</tr>
</tbody>
注意:这种方法在标题和数据单元格之间创建了非常精确的关联,但它使用了大量的标记,并且没有留下任何错误空间。对于大多数表格,scope
方法通常就足够了。
主动学习:玩转作用域和标题
- 在最后这个练习中,我们希望您首先在新的目录中创建items-sold.html和minimal-table.css的本地副本。
- 现在尝试添加适当的
scope
属性,使这个表格更易于访问。 - 最后,尝试创建启动文件的另一个副本,这次通过使用
id
和headers
属性创建精确且明确的关联,使表格更易于访问。
注意:你可以查看我们的完成示例进行比较——参见items-sold-scope.html(也请查看此页面)和items-sold-headers.html(也请查看此页面)。