文档大纲困境

Avatar of Amelia Bellamy-Royds
Amelia Bellamy-Royds

DigitalOcean 为您旅程的各个阶段提供云产品。 立即开始使用 200 美元的免费信用额度!

在过去几周里,关于 HTML 标题的讨论在 Web 标准圈子中层出不穷。 也许您已经看到了一些博文、推文和 GitHub 问题线程。 标题一直是 HTML 的一部分 从 CERN 的第一个网站开始,因此在 25 年后发现它们有争议可能令人惊讶。 我将快速总结为什么它们仍然值得讨论,并提供大量指向其他来源的链接,然后将我自己的观点添加到讨论中。 如果你已经了解这场辩论,你可以 直接跳到“更大的困境”部分

到目前为止的故事……

HTML 使用标题(<h1><h2><h3>,依此类推,直到 <h6>)来标记随后文本部分的标题。 标题元素的数字(或级别)应该逻辑地对应于嵌套部分的树状结构,就像书籍包含章节、部分和子部分一样。

但是,HTML 标记最初没有办法在嵌套 DOM 结构中反映这种嵌套的逻辑结构。 与嵌套列表不同,嵌套标题实际上并没有嵌套在定义父部分的元素中。 不同级别的标题元素都是兄弟元素,也是它们提供的标题的段落的兄弟元素。 “部分”是一个纯粹的逻辑结构,而不是 DOM 结构,包含以标题开头并持续到遇到相同或更高级别的另一个标题为止的所有标记。

正如 Brian Kardell 指出,这在早期 HTML 的“扁平地球标记”中是完全合理的,其中标签只是插入到文本流中的排版指令。 HTML 页面作为树结构的概念后来才出现,当时所谓的动态 HTML 需要一个文档对象模型 (DOM) 来描述文本流和标签,作为脚本可以访问的数据结构。

不剧透结局,但 HTML 现在有一个 <section> 元素,可以(可选地)用来创建一个嵌套的 DOM 结构,以匹配您的逻辑标题结构。 <main><header><footer><article><aside><nav> 元素也都帮助创建了在 DOM 嵌套中反映的嵌套文档结构。

但是最初的标题模型还有另一个问题:它不能在模板系统中轻松地重新混合使用。 由于标题级别是由标签名称(<h1><h4>)而不是由其使用上下文来表达的,因此您无法轻松地在级别不同的其他上下文中重新使用相同的内容。 例如,博客可能会在许多上下文中使用相同的文章标题和简介段落:作为独立的博客文章页面;作为主索引页面的摘要;或者作为存档页面的摘要,其中还包含按月或年划分列表的标题。 文章标题应该是什么级别?

对分节元素的早期提案还包括一个无级别的 <h><heading> 元素,该元素将根据上下文分配一个级别。(实际上,这个 想法可以追溯到 HTML 最早的讨论。)但是,当分节元素最终添加到 HTML 时,它们被设计用来与现有的标题元素一起使用。 但是,规范定义了“文档大纲算法”,该算法将根据部分嵌套重新计算现有编号标题标签的标题级别。

使用文档大纲算法,您可以(理论上)对所有标题使用 <h1>,浏览器将根据其在 <article><section> 和相关元素中的嵌套来确定每个标题的级别。 大纲算法将确保页面中的顶部标题为级别 1,并且所有其他标题都以一致的顺序嵌套,没有跳过级别。 该 WHATWG 版本的大纲 还定义了处理 <hgroup> 元素中多部分标题的规则,因此子标题不会创建子部分。(W3C 版本的 HTML 5 声明 <hgroup> 已过时:多部分标题应该标记为部分 <header> 内的段落或主标题元素内的跨度。)

浏览器修改了其默认样式,因此嵌套部分内的标题将具有逐渐减小的字体大小(就像 <h3> 的默认样式比 <h2> 的字体大小小,而 <h2><h1> 的字体大小小)。 但是他们没有改变他们向屏幕阅读器使用的无障碍 API 公开标题级别的方式。 并且屏幕阅读器用户是唯一真正将标题级别作为用户界面的一部分来体验的用户。

屏幕阅读器在阅读标题时会宣布编号级别,并且它们允许用户快速浏览特定级别的标题。 根据 WebAIM 调查,三分之二的屏幕阅读器用户将标题扫描作为尝试在长网页上查找信息的第一个步骤。 对于这些用户来说,文档大纲算法的唯一影响是,一些新页面(热切地采用新规范)被呈现为级别一标题的扁平列表,没有任何结构。

为什么浏览器不会对无障碍标题级别使用大纲算法? 已经提出了很多论点,但最有说服力的论点是,它可能会改变现有网站向屏幕阅读器用户呈现的方式,并且目前尚不清楚这些改变是否大多是积极的。

Adrian Roselli 在 “没有文档大纲” 中汇编了关于未实现的大纲规范引起的问题的讨论的良好概述。 该 最新的 W3C HTML 规范 仅使用文档大纲算法来建议作者如何将其编号标题标签与嵌套的分节元素同步。 该 WHATWG HTML 规范 仍然将完整的大纲算法描述为规范性要求,尽管有一个 开放问题,其中许多人建议完全删除它。 正如 WHATWG 规范编辑 Domenic Denicola 所说

在某个时刻,我们不能声称用户代理是损坏的。 相反,他们拒绝了我们的更改请求。

当前的辩论

最新的辩论热潮是由 Jonathan Neal 在 W3C HTML 规范上提交的关于重新提出难以捉摸的 <h> 元素的问题 引发的。 提案的关键是 <h> 标题元素可以具有由分节元素定义的嵌套级别,同时仍然允许现有编号标题标签的级别由其标签名称确定。 作者可以通过使用新标签来选择加入大纲算法。 在浏览器支持 <h> 之前,可以使用 JavaScript(或服务器端)polyfill 来计算标题级别并将它们添加到 DOM 中,并带有 ARIA 属性:role="heading"aria-level="3" 会告诉浏览器将元素视为级别 3 标题,用于无障碍目的,无论标签名称或嵌套如何,因此页面作者最终对任何标题混淆负全部责任。

该问题页面以及更长的链接博文中有很多好的讨论。 赞成添加新元素的主要论据是它不会改变现有内容的含义。 除了 Neal 在 GitHub 上的论据之外,Brian Kardell 关于自定义元素和 polyfill 的提案 从这个角度解决了这个问题。 另一方面,Jake Archibald 认为应该修复我们已经拥有的元素

修复现有 Web 所需的工作是创建执行相同操作但不会修复现有 Web 的新元素的一个子集。

换句话说,如果大纲算法如此出色,以至于值得创建一个新元素,为什么不简单地对现有元素实现大纲算法呢?

如果你仍然难以理解为什么没有人就如何处理像 HTML 标题一样看似简单的东西达成一致,Brian Kardell 在 第二篇文章中帮助消除了所有技术细节

更大的困境

在所有关于如何为网页创建文档大纲的讨论之下,存在着一个隐藏的假设。 讨论如何创建文档大纲,假设网页的结构可以定义为大纲:作为标题的嵌套级别定义其重要性的树。

我个人认为,一个简单的嵌套大纲无法捕捉到 HTML 标题级别所传达的所有意义级别,因为它们在 Web 上使用。 我将稍后说明原因。 但是,所有讨论都集中在这一类型的大纲上是有原因的:因为这是屏幕阅读器期望的这一类型的大纲。

对于大多数 Web 用户和 Web 作者来说,文档大纲是无关紧要的。 他们不知道也不关心标题和部分是如何嵌套的,他们只看到屏幕上的内容。 并且在今天的绝大多数网页中,屏幕上的内容是一个二维的内容布局,其中一些内容是嵌套的,而另一些内容是独立的,每个部分通过布局、颜色和排版赋予了隐含的重要性关系。

所以,我们应该讨论的问题不是“我们应该如何为标题分配大纲级别?” 而是:“我们如何总结网页的有意义结构,以便使用辅助技术的人可以轻松找到内容?”

我个人希望浏览器为所有用户添加一个功能,以表格的形式显示大纲,并使其可以通过键盘快速导航到标题。也许如果他们做到了,更多的网页作者会关注他们的纲要看起来像什么。但浏览器没有这样做,所以大多数作者也没有这样做。

如果你想看看你的网站标题大纲是什么样的——以及它在理论上使用文档大纲算法会是什么样子——你可以使用W3C Nu HTML 验证器服务,并选中“显示大纲”选项。

就目前而言,文档大纲只对屏幕阅读器用户具有日常重要性,而这些用户目前习惯于处理网页中不稳定的标题级别混乱。我相信许多屏幕阅读器用户会感谢标题级别得到修复。但是,为屏幕阅读器用户修复标题不仅仅意味着创建没有跳过级别编号的整齐嵌套标题树。这意味着创建准确反映网页创建者意图的标题结构,这种意图是视觉用户从样式和布局中推断出来的。为了做到这一点,我们需要考虑如何将意义传达给所有不是通过数字级别宣布每个标题来听取每个标题的网页用户。

语言由使用它的人定义

HTML 在计算机代码语言中是独一无二的,因为它定义了如此多的结构而没有为它们分配特定的行为。计算机代码中的意义被称为语言的语义方面,与语法结构的语法结构相对。但在大多数编程语言中,内置对象的语义方面仍然与计算机指令紧密相连。在 JavaScript 中,new Date()new Promise() 具有相同的语法——调用构造函数——但你的 JS 解释器理解这两个对象名称之间的语义区别,并对每个对象表现出截然不同的行为。

相比之下,HTML <article><section> 并没有附带任何关于你的 Web 浏览器应该如何处理它的指令(除了未实现的大纲算法之外)。相反,这两者之间的区别在于内容的意义,一种为从一个人(网站作者)到另一个人(读者)传递的信息提供机器可读注释的方式。

人类交流中的意义很难定义,而且从不静止。但最重要的是,它是由使用语言的人定义的。词典汇编了所用意义的摘要,但它们并没有限制它们。如果人们开始用新的和不同的方式使用词语,词典(如果它足够好)将更新它们的定义。

当我上小学的时候,一位图书管理员向我们展示了多卷本的牛津英语词典,向我们介绍了一些奇奇怪怪的词语。Google* 是指用 1 后面跟着 100 个零表示的数字(在科学记数法中为 10100)。很疯狂,对吧?谁会需要知道这样的词呢?但时代变了。2006 年,OED 添加了一个新的定义,google 作为一个动词(意思是使用 Google 搜索引擎),在现代英语对话中,它的使用频率可能比数字量高出 googol 倍。

*更正:正如马克在评论中指出的那样,我多年前看到的词语的正确拼写实际上是googol。现在我不知道该相信什么了。

当涉及到 HTML 标签的意义时,相当于词典的是两个竞争的 HTML 规范(WHATWGW3C)。就像词典一样,它们最初都是为了描述当前使用的语言而作的努力。

存在两种不同的 HTML 规范这一事实使讨论更改变得更加困难,但也强烈突出了 HTML 作为一种语言的集体、基于共识的性质。没有一个定义文档来设定 HTML 的规则。HTML 由编写它的人和解释它的 Web 浏览器定义。

当然,事情并不像看起来那样简单。HTML 不仅由人类使用,还由计算机使用。而计算机不擅长处理模糊和变化的意义。

每当你要求计算机对你的内容执行操作时——例如,告诉屏幕阅读器这个网站中有哪些标题以及它们的组织方式——它需要明确的规则来指导如何执行操作。如果一些网页作者以一种方式使用标题标签,而一些作者则以不同的意义使用相同的标签,你的浏览器将需要额外的规则来判断哪一个是哪一个——否则它会出错,至少有时会出错。

网络标准运动的驱动力是希望所有 Web 浏览器对网页代码的反应方式(大致)相同。这意味着在标准文档中定义新功能,然后才能在网络上使用它们。它们不是描述性的,像词典(定义事物是什么),而是规范性的,像法律法规(定义事物应该是什么)。

标准开发的缓慢速度,以及来自浏览器团队的大量投入,应该确保最终结果既具有规范性,也具有描述性,至少对于描述浏览器行为的语言部分而言。但它并不总是有效。两种规范中都有很多细节与实际的浏览器行为不符。W3C 的问题库甚至有一个令人欣慰的命名标签更好地匹配现实,旨在修复这些部分。

而这仅仅是针对描述浏览器应该做什么的功能。那么,所有定义内容语义的 HTML 元素呢?难道它们不应该“更好地匹配现实”吗?

几个月前,Sara Soueidan 建议 W3C HTML 工作组,也许<address> 元素应该对所有地址有效(而不仅仅是页面所有者联系地址)。在她之前,许多人肯定提出了同样的抱怨。但这一次,发生了某些事情。在进行了一些粗略的数据抓取之后,这些数据表明,实际的野外使用并没有局限于最初的定义,因此,对W3C 规范中的定义进行了更新

这会有什么区别吗?也许不会。浏览器除了将<address> 设置为斜体外,什么也不做。而WHATWG HTML 规范仍然保留着旧的定义。但这意味着规范更接近于描述代码在网络上的实际使用方式,而不是某人曾经想象的可能使用方式。

这最终让我们回到了标题:它们在网络上是如何实际使用的?对于网页作者和 Web 浏览器,是否有可能定义一套规范性的指令,以确保标题的意义能够正确地传达给屏幕阅读器(以及潜在的其他软件)?

标题的多种含义

什么是标题?它是文档一部分的简短标题。本节的标题是“标题的多种含义”。到目前为止,一切都很好。

但并非所有标题都相同。

有大的标题

大标题

还有非常小的标题

一个小的标题,它几乎不是标题

如果你检查代码,你会发现其中一个是<h1>,另一个是<h6>。它们都用<figure> 标签包裹起来,根据文档大纲算法,应该将它们封装起来并防止它们弄乱主文档大纲。但我们现在都知道了文档大纲算法实际上并没有被 Web 浏览器使用,因此对于任何因错误而最终出现在文章中间的屏幕阅读器用户,我们表示歉意。

对于任何使用现代浏览器用眼睛阅读本文的人来说,这两个标题之间的区别是由字体大小,以及可能的字体样式传达的。确切的细节将取决于你是在查看网站的 CSS 还是浏览器的阅读模式 CSS,以及 Chris 多久更改一次 CSS-Tricks 的样式。但除非 Chris 真的把事情搞砸了,否则对于视觉阅读者来说,<h1><h6>更大、更重要将是显而易见的。我们可以更改 CSS,使它们看起来完全一样,但在这一点上,很难理解你为什么要这样做。如果你想让它们看起来相同,为什么不使用相同的标签名呢?

所以让我们更进一步,将这两个标题与它们之间的填充文本放在一起。以下是一种我们可以做到这一点的方法,使用一个主标题,一些文本,然后是一个副标题和一些更多文本

查看 CodePen 上 Amelia Bellamy-Royds (@AmeliaBR) 编写的标题大纲示例 #1

以下是排列相同标题和段落 的另一种方法

查看 CodePen 上 Amelia Bellamy-Royds (@AmeliaBR) 编写的标题大纲示例 #2

这是第三种方法

查看 Pen 标题大纲示例 #3 by Amelia Bellamy-Royds (@AmeliaBR) on CodePen.

如果你只查看这些 Pen 的结果标签,并用你的眼睛来查看,你可能会被原谅认为第二个和第三个是相同的,并且与第一个非常不同。从视觉上看,示例 #2 和示例 #3 都有一个带有大标题的主部分和一个带有小标题的侧边栏部分。区别在于一个使用 <div> 元素来创建结构,而另一个使用 HTML 分区元素。

如果你已经读到这里,你可能不会太惊讶地发现,这两个示例在由 HTML 文档大纲算法处理时会创建不同的结构。在该算法下,div 会被忽略,因此示例 #2 的处理方式与示例 #1 完全相同:一个主标题,一些段落文本,然后是一个副标题和另一个段落。该 大纲 并没有表明侧边栏与主文章是一个独立的平行结构。

  1. 一个大标题

    1. 一个标题很小,几乎不是标题

相反,如果我 对示例 #3 运行大纲算法,它告诉我,存在一个没有标记的主文档(没有顶级标题),它有两个相等同级的子元素(两个标题都被视为 2 级)。所以现在它清楚地传达了平行结构,但没有传达标题重要性的差异。

  1. [没有标题的正文元素]

    1. 一个大标题
    2. 一个标题很小,几乎不是标题

我认为这 两种 大纲都没有准确地描述这种视觉布局。基于标签名称的大纲也不行,它不仅将侧边栏视为嵌套在主文章中,而且还被我使用 <h6> 的方式所吸引,该页面没有 <h2/3/4/5> 元素。

如果我被要求向某人描述这个布局,我会告诉他们 件事

  • 有两个并排的部分;
  • 其中一个部分比另一个部分更重要。

组件的相对重要性与嵌套结构(或在这个简单示例中的缺乏)是分开的信息。在一个更复杂的示例中,你将有一些内容块,它们具有有意义的嵌套标题(例如本文),而其他内容块(例如侧边栏或下面的评论部分)具有平行的独立大纲,其内部标题级别与第一个内容块中的标题级别无关。将每个平行块视为相等会忽略它们在标记中获得的相对重要性。但是将这些额外的标题附加到主文章的末尾,仅仅因为两者之间没有更大的标题,似乎更糟糕。

即使组件是嵌套的,它们通常也有一个独立于周围部分数量的重要级别。我为 O'Reilly 撰写了有关 SVG 的书籍。我们用于创建书籍的标记被转换为 HTML。书籍(一级标题)有章节(二级标题),章节有部分(三级标题),有时有子部分甚至子子部分(四级和五级)。但它也包含示例、警告说明和侧边栏,所有这些都可能拥有自己的标题,这些标题的样式将相同,无论该组件是否位于常规部分或子子部分中。如果我们使用“正确”的 HTML 标题元素,它们将具有不同的标签名称,具体取决于部分深度,但样式将相同。

在网页设计和内容管理中,我们有两种截然不同的方式来谈论标题的级别:重要级别或嵌套级别。我认为网页标准人员无法就将标题转换为大纲的算法达成一致的主要原因是,人们希望找到一种算法,使两者都同意,而它们通常不同意。

也许真正需要的是停止谈论大纲,就好像它们重新对标题重要级别进行编号一样。停止告诉 Web 开发人员他们在使用对他们的内容有意义的标题级别方面是错误的。让上下文定义大纲嵌套,但不要将大纲嵌套定义为可与标签名称互换。理想情况下,找到一种方法,使浏览器能够向屏幕阅读器传达部分的嵌套结构 原始标题级别数字,这样屏幕阅读器就可以让用户通过嵌套结构进行导航,同时仍然传达每个标题的相对重要性。

然后关注真正的问题

我们如何概括网页的有意义结构,以便使用辅助技术的人可以轻松找到内容?

我的直觉是,使用分区元素的大纲通常比仅基于标签名称的大纲更适合导航,但细节需要改进。特别是

给我看数据

但这只是我的看法。

为了让浏览器或屏幕阅读器更改其行为(更不用说说服使用标题进行内容的所有数十万 Web 开发人员了),我们需要的东西不仅仅是直觉和意见。如我所 在早期提出的论点,我们需要一些数据。JakeBrian 也呼应了这种呼吁。

但我们需要的这类数据不是网络爬虫可以收集的类型。我们需要关于意义的数据,只有真正的人类大脑才能提供这种意义。

HTML 分区元素已经存在很多年了。它们不再是理论上的东西了。它们是你们 Web 开发人员用来进行交流的语言的一部分。如果你正在使用分区元素,希望你有一个理由。当你选择一个标题标签时,希望你有一个理由。现在是时候审查 HTML 标准,以确保它们反映大多数开发人员使用的理由和意义了。

因此,我要求你:通过 HTML 验证器中的两个大纲构建器 运行你最喜欢的网站(你构建的或你使用的网站)。

  • 这两个大纲中的任何一个都有意义吗?
  • 你是否可以通过合理的标记调整来使它们有意义,你可以使用你的构建系统或组件框架来实现这些调整?
  • 哪个大纲更好?
  • 文档结构的哪些方面会导致最大的问题?

在进行这些工作时,还有一个问题

作为一名 Web 用户,你希望如何能够基于标题或大纲访问和浏览文档?