1. 1 概述
    1. 1.1 这是 HTML5 吗?
    2. 1.2 背景
    3. 1.3 受众
    4. 1.4 范围
    5. 1.5 历史
    6. 1.6 设计说明
      1. 1.6.1 与其他规范的兼容性
      2. 1.6.2 可扩展性
    7. 1.7 HTML 与 XML 语法
    8. 1.8 此规范的结构
      1. 1.8.1 排版约定
    9. 1.9 关于 HTML 的简要介绍
      1. 1.9.1 使用 HTML 编写安全应用程序
      2. 1.9.2 使用脚本 API 时常见的陷阱
      3. 1.9.3 如何在编写 HTML 时发现错误:验证器和一致性检查器
    10. 1.10 作者的一致性要求
      1. 1.10.1 表现性标记
      2. 1.10.2 语法错误
      3. 1.10.3 对内容模型和属性值的限制
    11. 1.11 建议阅读

1 概述

1.1 这是 HTML5 吗?

简而言之:是的。

更详细地说:"HTML5" 这个词被广泛用作流行语来指代现代 Web 技术,其中许多技术(尽管并非全部)是在 WHATWG 开发的。本文件就是其中之一;其他技术可从 WHATWG 标准概述 中获取。

1.2 背景

HTML 是万维网的核心标记语言。最初,HTML 主要被设计为一种用于语义描述科学文档的语言。然而,它的一般设计使其能够在随后的几年中被改编为描述多种其他类型的文档,甚至应用程序。

1.3 受众

本规范面向使用本规范中定义的特性编写文档和脚本的作者。

对于那些对 Web 技术没有起码了解的读者来说,本文件可能并不适合,因为在某些地方,它牺牲了清晰度以求精确,牺牲了简洁性以求完整。更易于理解的教程和创作指南可以提供更温和的介绍。

特别是,熟悉 DOM 的基础知识对于完全理解本规范中一些更技术性的部分是必要的。对 Web IDL、HTTP、XML、Unicode、字符编码、JavaScript 和 CSS 的了解在某些地方也会有所帮助,但并非必不可少。

1.4 范围

本规范仅限于提供语义级标记语言和相关的语义级脚本 API,用于创作从静态文档到动态应用程序的各种 Web 可访问页面。

本规范的范围不包括提供用于媒体特定呈现自定义的机制(尽管 Web 浏览器默认呈现规则包含在本规范的末尾,并且作为语言的一部分提供了一些用于挂钩 CSS 的机制)。

本规范的范围不是描述一个完整的操作系统。特别是,硬件配置软件、图像处理工具以及用户预计每天使用高端工作站的应用程序不在本规范范围内。在应用程序方面,本规范专门针对用户预计偶尔使用或定期使用但来自不同位置,并且 CPU 要求较低的应用程序。此类应用程序的示例包括在线购买系统、搜索系统、游戏(尤其是多人在线游戏)、公共电话簿或地址簿、通信软件(电子邮件客户端、即时通讯客户端、讨论软件)、文档编辑软件等。

1.5 历史

在最初的五年(1990-1995 年),HTML 经历了许多修订并进行了许多扩展,主要是在 CERN 以及之后在 IETF 主持下进行。

随着 W3C 的创建,HTML 的开发再次改变了场地。1995 年,第一次中止的扩展 HTML 的尝试被称为 HTML 3.0,然后让位于更务实的被称为 HTML 3.2 的方法,该方法于 1997 年完成。HTML4 在同年晚些时候紧随其后。

次年,W3C 成员决定停止发展 HTML,而是开始着手开发一个基于 XML 的等效语言,称为 XHTML。这项工作从基于 XML 的 HTML4 的重构开始,被称为 XHTML 1.0,它除了新的序列化之外没有添加任何新特性,并在 2000 年完成。在 XHTML 1.0 之后,W3C 的重点转向了在 XHTML 模块化旗帜下,使其他工作组更容易扩展 XHTML。与之平行的是,W3C 还开发了一种与早期 HTML 和 XHTML 语言不兼容的新语言,并将其命名为 XHTML2。

大约在 1998 年 HTML 的发展停止时,浏览器供应商开发的 HTML API 的部分内容以 DOM Level 1(在 1998 年)和 DOM Level 2 Core 以及 DOM Level 2 HTML(从 2000 年开始,并于 2003 年完成)的名义进行了规范化并发布。这些工作随后逐渐消失,一些 DOM Level 3 规范于 2004 年发布,但工作组在所有 Level 3 草案完成之前就关闭了。

2003 年,XForms 的发布(一项定位为下一代 Web 表单的技术)重新燃起了对 HTML 本身进行发展的兴趣,而不是寻找它的替代品。这种兴趣来自于这样一个认识,即 XML 作为 Web 技术的部署仅限于全新的技术(如 RSS 和后来的 Atom),而不是作为现有部署技术的替代品(如 HTML)。

一个概念证明,展示了扩展 HTML4 的表单以提供 XForms 1.0 引入的许多特性而无需浏览器实现与现有 HTML 网页不兼容的渲染引擎是这种重新燃起的兴趣的第一个结果。在这一早期阶段,虽然草案已经公开发布,并且已经从各个来源征求意见,但该规范仅在 Opera Software 的版权下。

2004 年,W3C 工作坊对重新开放 HTML 的发展进行了测试,在工作坊上,Mozilla 和 Opera 联合向 W3C 提交了关于 HTML5 工作的几个核心原则(如下所述)以及上述仅涵盖表单相关特性的早期草案提案。该提案被拒绝,理由是该提案与之前为 Web 发展所选择的路线相冲突;W3C 员工和成员投票继续开发基于 XML 的替代方案。

此后不久,Apple、Mozilla 和 Opera 联合宣布他们打算在名为 WHATWG 的新场所的保护伞下继续这项工作。创建了一个公开邮件列表,并将草案移至 WHATWG 网站。随后修改了版权,将其共同归属于这三家供应商所有,并允许对规范进行再利用。

WHATWG 基于几个核心原则,特别是技术需要向后兼容,规范和实现需要匹配,即使这意味着改变规范而不是实现,以及规范需要足够详细,以使实现能够实现完全的互操作性,而无需相互反向工程。

后一个要求尤其需要 HTML5 规范的范围包括之前在三个单独的文档中指定的內容:HTML4、XHTML1 和 DOM2 HTML。它还意味着包含比以前被认为是规范的更多细节。

2006 年,W3C 表明有兴趣参与 HTML5 的开发,并在 2007 年组建了一个工作组,负责与 WHATWG 合作开发 HTML5 规范。Apple、Mozilla 和 Opera 允许 W3C 在 W3C 版权下发布该规范,同时在 WHATWG 网站上保留一个具有较少限制性许可证的版本。

多年来,这两个组织一直合作。然而,在 2011 年,这两个组织得出结论,他们的目标不同:W3C 想要发布一个 "完成的" "HTML5" 版本,而 WHATWG 想要继续开发一个关于 HTML 的活的标准,不断维护规范,而不是将其冻结在具有已知问题的状态,并在需要时添加新特性以发展平台。

2019 年,WHATWG 和 W3C 签署了一项协议,在未来合作开发 HTML 的单一版本:本文件。

1.6 设计说明

必须承认,HTML 的许多方面乍一看似乎毫无意义且不一致。

HTML、其支持的 DOM API 以及许多支持技术都是在几十年间由一大群具有不同优先级的人员开发的,这些人中许多人并不知道彼此的存在。

因此,特性来自许多来源,并且并非总是以特别一致的方式设计。此外,由于 Web 的独特特性,实现错误通常会成为事实上的标准,现在也成为法律上的标准,因为内容通常在它们能够被修复之前就被无意中以依赖于它们的方式编写。

尽管如此,还是努力遵守某些设计目标。这些目标将在接下来的几个小节中进行描述。

1.6.1 与其他规范的兼容性

本规范与许多其他规范交互并依赖于它们。不幸的是,在某些情况下,相互冲突的需求导致本规范违反了这些其他规范的要求。每当出现这种情况时,违规行为都会被记录为一个 "故意违规",并且违规的原因也会被记录下来。

1.6.2 可扩展性

HTML 拥有各种可扩展性机制,可用于以安全的方式添加语义。

1.7 HTML 与 XML 语法

本规范定义了一种用于描述文档和应用程序的抽象语言,以及一些用于与使用这种语言的资源的内存表示形式进行交互的 API。

内存表示形式被称为“DOM HTML”,简称“DOM”。

可以使用各种具体语法来传输使用这种抽象语言的资源,其中两个定义在本规范中。

第一个这样的具体语法是 HTML 语法。这是大多数作者建议的格式。它与大多数旧版 Web 浏览器兼容。如果文档使用 text/html MIME 类型 传输,则 Web 浏览器会将其作为 HTML 文档进行处理。本规范定义了最新的 HTML 语法,简称为“HTML”。

第二个具体语法是 XML。当文档使用 XML MIME 类型(例如 application/xhtml+xml)传输时,Web 浏览器会将其视为 XML 文档,由 XML 处理器进行解析。请提醒作者,XML 和 HTML 的处理有所不同;特别是,即使是轻微的语法错误也会阻止标记为 XML 的文档完全呈现,而在 HTML 语法中这些错误会被忽略。

HTML 的 XML 语法以前被称为“XHTML”,但本规范不使用该术语(除其他原因外,因为 MathML 和 SVG 的 HTML 语法中没有使用此类术语)。

DOM、HTML 语法和 XML 语法无法全部代表相同的内容。例如,名称空间无法使用 HTML 语法表示,但它们在 DOM 和 XML 语法中受支持。同样,使用 noscript 功能的文档可以使用 HTML 语法表示,但无法使用 DOM 或 XML 语法表示。包含字符串“-->”的注释只能在 DOM 中表示,不能在 HTML 和 XML 语法中表示。

1.8 本规范的结构

本规范分为以下主要部分

介绍
提供 HTML 标准背景的非规范性材料。
通用基础设施
一致性类别、算法、定义以及规范其余部分的通用基础。
HTML 文档的语义、结构和 API
文档由元素构成。这些元素使用 DOM 形成树。本节定义了此 DOM 的功能,以及介绍所有元素的通用功能,以及定义元素中使用的概念。
HTML 的元素
每个元素都具有预定义的含义,在本节中进行了说明。还提供了有关作者如何使用元素的规则。这包括 HTML 的主要功能,例如视频播放和字幕、表单控件和表单提交,以及称为 HTML 画布的二维图形 API。
微数据
本规范介绍了一种机制,用于向文档添加机器可读的注释,以便工具可以从文档中提取名称-值对树。本节描述了这种机制。本节还定义了一些用于联系信息、日历事件和许可作品的示例微数据词汇。
用户交互
HTML 文档可以提供多种机制,供用户与内容交互并修改内容,在本节中进行了描述,例如焦点的运作方式以及拖放。
加载网页
HTML 文档并非孤立存在——本节定义了许多影响处理多个页面的环境的功能,例如 Web 浏览器。
Web 应用程序 API
本节介绍了在 HTML 中对应用程序进行脚本编写的基本功能。
Web 工作线程
本节定义了用于 JavaScript 背景线程的 API。
工作线程
本节定义了用于需要在主 JavaScript 执行环境之外运行 JavaScript 的 API 的基础设施。
通信 API
本节描述了使用 HTML 编写的应用程序可以使用的一些机制,与运行在同一客户端上的不同域的其他应用程序进行通信。它还介绍了一种称为服务器发送事件或 EventSource 的服务器推送事件流机制,以及一种称为 Web 套接字的用于脚本的双向全双工套接字协议。
Web 存储
本节定义了一种基于名称-值对的客户端存储机制。
HTML 语法
XML 语法
如果这些功能不能以序列化形式表示并发送给其他人,那么所有这些功能都将毫无用处,因此这些部分定义了 HTML 和 XML 的语法。

还有一些附录,列出了 已弃用功能IANA 考虑因素,以及几个索引。

1.8.1 排版约定

这是定义、要求或说明。

这是一个备注。

这是一个示例。

这是一个开放性问题。

这是一个警告。

variable = object.method([optionalArgument])

这是一个针对作者的备注,描述了接口的使用方式。

/* this is a CSS fragment */

术语的定义实例用 this 标记。该术语的使用用 thisthis 标记。

元素、属性或 API 的定义实例用 this 标记。对该元素、属性或 API 的引用用 this 标记。

其他代码片段用 like this 标记。

变量用 this 标记。

在某些情况下,要求以包含条件和相应要求的列表形式给出。在这种情况下,适用于某个条件的要求始终是该条件后面出现的第一个要求集,即使对于那些要求存在多个条件集也是如此。此类情况将按如下所示显示

这是一个条件
这是另一个条件
这是适用于上述条件的要求。
这是第三个条件
这是适用于第三个条件的要求。

1.9 HTML 简介

基本的 HTML 文档如下所示

<!DOCTYPE html>
<html lang="en">
 <head>
  <title>Sample page</title>
 </head>
 <body>
  <h1>Sample page</h1>
  <p>This is a <a href="demo.html">simple</a> sample.</p>
  <!-- this is a comment -->
 </body>
</html>

HTML 文档由元素和文本树组成。每个元素在源代码中用 开始标记(例如“<body>”)和 结束标记(例如“</body>”)表示。(在某些情况下,某些开始标记和结束标记可以 省略,并由其他标记隐含。)

标记必须嵌套,以便元素全部完全包含在彼此内部,而不会重叠

<p>This is <em>very <strong>wrong</em>!</strong></p>
<p>This <em>is <strong>correct</strong>.</em></p>

本规范定义了一组可以在 HTML 中使用的元素,以及有关元素嵌套方式的规则。

元素可以具有属性,这些属性控制元素的工作方式。在下面的示例中,有一个 超链接,它是使用 a 元素及其 href 属性形成的

<a href="demo.html">simple</a>

属性 放置在开始标记内,由 名称 组成,用“=”字符分隔。如果属性值不包含 ASCII 空格 或者不包含 " ' ` = <>,则可以保持 不加引号。否则,它必须用单引号或双引号加引号。如果值为空字符串,则该值以及“=”字符可以完全省略。

<!-- empty attributes -->
<input name=address disabled>
<input name=address disabled="">

<!-- attributes with a value -->
<input name=address maxlength=200>
<input name=address maxlength='200'>
<input name=address maxlength="200">

HTML 用户代理(例如 Web 浏览器)然后会解析此标记,将其转换为 DOM(文档对象模型)树。DOM 树是文档的内存表示形式。

DOM 树包含几种类型的节点,特别是 DocumentType 节点、Element 节点、Text 节点、Comment 节点,以及在某些情况下,ProcessingInstruction 节点。

本节开头的标记片段 将转换为以下 DOM 树

此树的文档元素html元素,它是 HTML 文档中始终位于该位置的元素。它包含两个元素,headbody,以及它们之间的一个Text节点。

DOM 树中比最初预期的要多出许多Text节点,因为源代码包含许多空格(此处用 "␣" 表示)和换行符("⏎"),它们最终都成为 DOM 中的Text节点。但是,由于历史原因,原始标记中的并非所有空格和换行符都出现在 DOM 中。特别是,head开始标记之前的空格最终会被静默删除,而body结束标记之后的空格最终会被放置在body的末尾。

head元素包含一个title元素,该元素本身包含一个Text节点,其中包含文本 "Sample page"。类似地,body元素包含一个h1元素,一个p元素和一个注释。


此 DOM 树可以从页面中的脚本进行操作。脚本(通常用 JavaScript 编写)是可以在页面中使用script元素或使用事件处理程序内容属性嵌入的小型程序。例如,以下是一个带有脚本的表单,该脚本将表单的output元素的值设置为 "Hello World"。

<form name="main">
 Result: <output name="result"></output>
 <script>
  document.forms.main.elements.result.value = 'Hello World';
 </script>
</form>

DOM 树中的每个元素都由一个对象表示,这些对象具有 API,因此可以对其进行操作。例如,链接(例如上面树中的a元素)可以通过几种方式更改其 "href" 属性。

var a = document.links[0]; // obtain the first link in the document
a.href = 'sample.html'; // change the destination URL of the link
a.protocol = 'https'; // change just the scheme part of the URL
a.setAttribute('href', 'https://example.com/'); // change the content attribute directly

由于 DOM 树被用作表示 HTML 文档的方式,当它们被实现(尤其是像 Web 浏览器这样的交互式实现)处理和呈现时,因此本规范主要用 DOM 树的术语来表达,而不是上面描述的标记。


HTML 文档表示交互式内容的媒体无关描述。HTML 文档可能被渲染到屏幕上,或通过语音合成器,或在盲文显示器上。为了影响这种渲染的确切方式,作者可以使用 CSS 等样式语言。

在以下示例中,页面已使用 CSS 设置为黄色背景和蓝色文字。

<!DOCTYPE html>
<html lang="en">
 <head>
  <title>Sample styled page</title>
  <style>
   body { background: navy; color: yellow; }
  </style>
 </head>
 <body>
  <h1>Sample styled page</h1>
  <p>This page is just a demo.</p>
 </body>
</html>

有关如何使用 HTML 的更多详细信息,鼓励作者查阅教程和指南。本规范中包含的一些示例也可能有用,但初学者作者需注意,本规范出于必要,以可能难以理解的详细程度定义了语言。

1.9.1 使用 HTML 编写安全应用程序

当 HTML 用于创建交互式站点时,需要谨慎避免引入漏洞,攻击者可以通过这些漏洞损害站点本身或站点用户的完整性。

对这个问题进行全面的研究超出了本文档的范围,强烈建议作者更详细地研究这个问题。但是,本节试图快速介绍 HTML 应用程序开发中的一些常见缺陷。

Web 的安全模型基于 "来源" 的概念,相应地,许多对 Web 的潜在攻击都涉及跨源操作。 [ORIGIN]

未验证用户输入
跨站脚本 (XSS)
SQL 注入

在接受不受信任的输入时,例如用户生成的内容(例如文本评论)、URL 参数中的值、来自第三方站点的消息等,必须在使用前验证数据,并在显示时正确转义。如果没有这样做,可能会允许恶意用户执行各种攻击,从潜在的良性攻击(例如提供虚假用户信息,例如负年龄)到严重的攻击(例如每次用户查看包含信息的页面时运行脚本,可能在过程中传播攻击),到灾难性的攻击(例如删除服务器中的所有数据)。

在编写过滤器以验证用户输入时,必须始终使用安全列表过滤器,允许已知安全结构并禁止所有其他输入。禁止已知不良输入并允许所有其他输入的黑名单过滤器并不安全,因为并非所有不良内容都是已知的(例如,因为它们可能是将来发明的)。

例如,假设一个页面查看其 URL 的查询字符串以确定要显示的内容,然后站点将用户重定向到该页面以显示消息,如下所示

<ul>
 <li><a href="message.cgi?say=Hello">Say Hello</a>
 <li><a href="message.cgi?say=Welcome">Say Welcome</a>
 <li><a href="message.cgi?say=Kittens">Say Kittens</a>
</ul>

如果消息只是显示给用户,而没有转义,则恶意攻击者可以创建包含脚本元素的 URL

https://example.com/message.cgi?say=%3Cscript%3Ealert%28%27Oh%20no%21%27%29%3C/script%3E

如果攻击者随后说服受害用户访问此页面,则攻击者选择的脚本将在页面上运行。此类脚本可以执行任意数量的恶意操作,仅受站点提供的功能限制:例如,如果站点是电子商务商店,则此类脚本可能会导致用户在不知情的情况下进行任意数量的不必要的购买。

这被称为跨站脚本攻击。

有许多结构可用于试图欺骗站点执行代码。以下是鼓励作者在编写安全列表过滤器时考虑的一些结构

跨站请求伪造 (CSRF)

如果站点允许用户进行具有用户特定副作用的表单提交,例如以用户的名义在论坛上发布消息、进行购买或申请护照,那么务必验证该请求确实是用户有意发出的,而不是由另一个站点欺骗用户在不知情的情况下发出请求。

这个问题存在的原因是 HTML 表单可以提交到其他来源。

站点可以通过使用用户特定隐藏令牌填充表单,或通过检查所有请求的`Origin` 标头来防止此类攻击。

点击劫持

为用户提供执行用户可能不希望执行的操作的界面的页面需要进行设计,以避免用户被欺骗激活该界面。

用户被欺骗的一种方式是,恶意站点将受害站点放置在一个小的iframe中,然后说服用户点击,例如让用户玩反应游戏。当用户玩游戏时,恶意站点可以快速将 iframe 定位到鼠标光标下,就在用户即将点击时,从而欺骗用户点击受害站点的界面。

为了避免这种情况,鼓励那些不希望在框架中使用的站点仅在检测到它们不在框架中时才启用其界面(例如,通过将window对象与top属性的值进行比较)。

1.9.2 使用脚本 API 时应避免的常见缺陷

HTML 中的脚本具有 "运行至完成" 语义,这意味着浏览器通常会在执行任何其他操作(例如触发更多事件或继续解析文档)之前无中断地运行脚本。

另一方面,HTML 文件的解析是增量进行的,这意味着解析器可以在任何时候暂停以让脚本运行。这通常是一件好事,但这确实意味着作者需要注意避免在事件可能已经触发后挂钩事件处理程序。

有两种技术可以可靠地做到这一点:使用事件处理程序内容属性,或在同一脚本中创建元素并添加事件处理程序。后者是安全的,因为如前所述,脚本在进一步的事件可以触发之前会运行至完成。

这可能会以img元素和load事件的形式出现。该事件可能在元素被解析后立即触发,尤其是在图像已被缓存的情况下(这很常见)。

在这里,作者使用onload处理程序在img元素上捕获load事件

<img src="games.png" alt="Games" onload="gamesLogoHasLoaded(event)">

如果元素是通过脚本添加的,那么只要事件处理程序是在同一脚本中添加的,就不会错过事件

<script>
 var img = new Image();
 img.src = 'games.png';
 img.alt = 'Games';
 img.onload = gamesLogoHasLoaded;
 // img.addEventListener('load', gamesLogoHasLoaded, false); // would work also
</script>

但是,如果作者首先创建了img元素,然后在另一个脚本中添加事件监听器,则load事件可能在两者之间触发,导致它被错过

<!-- Do not use this style, it has a race condition! -->
 <img id="games" src="games.png" alt="Games">
 <!-- the 'load' event might fire here while the parser is taking a
      break, in which case you will not see it! -->
 <script>
  var img = document.getElementById('games');
  img.onload = gamesLogoHasLoaded; // might never fire!
 </script>

1.9.3 如何在编写 HTML 时捕获错误:验证器和一致性检查器

鼓励作者使用一致性检查器(也称为 *验证器*)来发现常见错误。WHATWG 在以下位置维护了此类工具的列表:https://whatwg.org/validator/

1.10 作者的一致性要求

与 HTML 规范的先前版本不同,本规范详细定义了对无效文档以及有效文档的处理要求。

但是,即使在大多数情况下对无效内容的处理都有很好的定义,文档的一致性要求仍然很重要:在实践中,互操作性(所有实现以可靠且相同或等效的方式处理特定内容的情况)并不是文档一致性要求的唯一目标。本节详细介绍了区分符合规范的文档和存在错误的文档的一些更常见的原因。

1.10.1 表现性标记

先前版本的 HTML 中的大多数表现性功能现在都不允许使用。表现性标记通常被发现存在一些问题

使用表现性元素会导致更差的辅助功能

虽然可以使用表现性标记以一种为辅助技术 (AT) 用户提供可接受体验的方式(例如,使用 ARIA),但这比使用语义上合适的标记要困难得多。此外,即使使用此类技术也无助于使网页对非 AT 非图形用户(例如文本模式浏览器用户)变得可访问。

另一方面,使用媒体独立标记提供了一种简单的方法,使文档能够以适合更多用户(例如文本浏览器用户)的方式进行创作。

更高的维护成本

维护以样式独立的方式编写的网站要容易得多。例如,更改使用<font color=""> 贯穿整个网站的颜色需要更改整个网站,而对基于 CSS 的网站进行类似更改只需更改一个文件即可。

更大的文档大小

表现性标记往往更冗余,因此会导致更大的文档大小。

出于这些原因,本版本中的 HTML 已删除表现性标记。此更改不应令人意外;HTML4 多年前已弃用表现性标记,并提供了一种模式(HTML4 Transitional)来帮助作者摆脱表现性标记;后来,XHTML 1.1 更进一步,完全弃用了这些功能。

HTML 中唯一剩下的表现性标记功能是 style 属性和 style 元素。在生产环境中,使用 style 属性有些不太建议,但它对于快速原型设计(其中它的规则可以稍后直接移动到单独的样式表中)和在单独的样式表将不方便的特殊情况下提供特定样式很有用。类似地,style 元素在联合或页面特定样式中可能很有用,但通常在样式应用于多个页面时,外部样式表可能更方便。

还值得注意的是,一些以前是表现性的元素在本规范中被重新定义为媒体独立的:bihrssmallu

1.10.2 语法错误

HTML 的语法受到限制,以避免各种问题。

不直观的错误处理行为

某些无效语法结构在解析时会生成高度不直观的 DOM 树。

例如,以下标记片段会导致一个 DOM,其中 hr 元素是对应 table 元素的更早的同级元素

<table><hr>...
带有可选错误恢复的错误

为了允许用户代理在受控环境中使用,而不必实现更奇怪和更复杂的错误处理规则,允许用户代理在遇到 解析错误 时失败。

错误处理行为与流式用户代理不兼容的错误

一些错误处理行为,例如上面提到的<table><hr>... 示例的行为,与流式用户代理(以一次通过方式处理 HTML 文件,不存储状态的用户代理)不兼容。为了避免与此类用户代理的互操作性问题,任何导致此类行为的语法都被视为无效。

可能导致信息集强制的错误

当基于 XML 的用户代理连接到 HTML 解析器时,可能会违反 XML 强制的某些不变式,例如元素或属性名称从不包含多个冒号,这将由 HTML 文件违反。处理此问题可能需要解析器将 HTML DOM 强制转换为与 XML 兼容的信息集。大多数需要此类处理的语法结构都被视为无效。(包含两个连续连字符或以连字符结尾的注释是 HTML 语法中允许的例外。)

导致性能明显下降的错误

某些语法结构会导致性能明显下降。为了阻止使用此类结构,它们通常被标记为不符合规范。

例如,以下标记会导致性能下降,因为所有未闭合的 i 元素都必须在每个段落中重建,从而导致每个段落中的元素越来越多

<p><i>She dreamt.
<p><i>She dreamt that she ate breakfast.
<p><i>Then lunch.
<p><i>And finally dinner.

此片段的生成的 DOM 将是

涉及脆弱语法结构的错误

存在一些由于历史原因而比较脆弱的语法结构。为了帮助减少意外遇到此类问题的用户数量,它们被标记为不符合规范。

例如,即使省略了结束分号,某些命名字符引用的解析也会发生。在属性中包含一个与字母后面的字母不构成命名字符引用的和号是安全的,但如果字母更改为构成命名字符引用的字符串,它们将被解释为该字符。

在此片段中,属性的值为“?bill&ted

<a href="?bill&ted">Bill and Ted</a>

但是,在以下片段中,属性的值实际上是“?art©”,而不是预期的“?art&copy”,因为即使没有最后的分号,“&copy”也与“&copy;”的处理方式相同,因此被解释为“©

<a href="?art&copy">Art and Copy</a>

为了避免此问题,所有命名字符引用都必须以分号结尾,并且使用没有分号的命名字符引用会被标记为错误。

因此,表示上述情况的正确方法如下

<a href="?bill&ted">Bill and Ted</a> <!-- &ted is ok, since it's not a named character reference -->
<a href="?art&amp;copy">Art and Copy</a> <!-- the & has to be escaped, since &copy is a named character reference -->
涉及传统用户代理中已知互操作性问题的错误

某些语法结构已知会导致传统用户代理中的特别微妙或严重问题,因此被标记为不符合规范,以帮助作者避免使用它们。

例如,这就是为什么不允许在未加引号的属性中使用 U+0060 GRAVE ACCENT 字符(`)。在某些传统用户代理中,它有时被视为引号字符。

另一个例子是 DOCTYPE,它需要触发 非怪癖模式,因为传统用户代理在 怪癖模式 下的行为通常很大程度上是无文档的。

可能导致作者遭受安全攻击的错误

某些限制纯粹是为了避免已知安全问题。

例如,使用 UTF-7 的限制纯粹是为了避免作者成为使用 UTF-7 的已知跨站点脚本攻击的受害者。 [UTF7]

作者意图不明确的情况

作者意图非常不明确的标记通常被标记为不符合规范。尽早更正这些错误可以使以后的维护更容易。

例如,不清楚作者是否打算将以下内容作为 h1 标题或 h2 标题

<h1>Contact details</h2>
可能是错字的情况

当用户犯了简单的错字时,如果能够尽早发现错误,则会很有帮助,因为这可以为作者节省大量调试时间。因此,本规范通常认为使用与本规范中定义的名称不匹配的元素名称、属性名称等是错误。

例如,如果作者输入了<capton> 而不是<caption>,这将被标记为错误,作者可以立即更正错字。

可能会干扰将来新语法的错误

为了允许将来扩展语言语法,某些原本无害的功能将被禁用。

例如,结束标记中的“属性”当前被忽略,但它们是无效的,以防将来对语言的更改利用该语法功能,而不会与已经部署(并且有效!)的内容发生冲突。

一些作者发现始终引用所有属性并始终包含所有可选标记的做法很有帮助,他们更喜欢从这种自定义中获得的一致性,而不是使用 HTML 语法的灵活性的简洁性带来的微不足道的优势。为了帮助此类作者,一致性检查器可以提供强制执行此类约定的操作模式。

1.10.3 对内容模型和属性值的限制

除了语言的语法外,本规范还对元素和属性的指定方式施加了限制。这些限制出于类似原因而存在

涉及语义可疑内容的错误

为了避免滥用具有定义含义的元素,定义了内容模型,这些模型限制了在嵌套没有价值的情况下元素的嵌套方式。

例如,本规范不允许在 kbd 元素中嵌套 section 元素,因为作者极不可能指示整个部分应该键入。

涉及表达语义冲突的错误

类似地,为了提醒作者注意元素使用中的错误,表达语义中的明显矛盾也被视为符合性错误。

例如,在以下片段中,语义是毫无意义的:分隔符不能同时是一个单元格,单选按钮也不能是一个进度条。

<hr role="cell">
<input type=radio role=progressbar>

另一个例子是 ul 元素的内容模型限制,它只允许 li 元素作为子元素。列表的定义只是由零个或多个列表项组成,因此如果 ul 元素包含除了 li 元素之外的其他内容,那么它的含义就不清楚了。

默认样式可能导致混淆的案例

某些元素具有默认样式或行为,这些样式或行为使某些组合容易导致混淆。如果这些组合有等效的替代方案,而没有这个问题,那么就会禁止这些混淆的组合。

例如,div 元素被呈现为 块级框,而 span 元素被呈现为 内联框。将 块级框 放在 内联框 中是毫无必要的混淆;因为嵌套 div 元素、嵌套 span 元素或在 div 元素中嵌套 span 元素都与在 span 元素中嵌套 div 元素具有相同的作用,但是只有后者涉及将 块级框 放在 内联框 中,因此后者组合被禁止。

另一个例子是 交互式内容 不能嵌套。例如,button 元素不能包含 textarea 元素。这是因为这种嵌套交互式元素的默认行为对于用户来说非常令人困惑。他们可以将这些元素并排放置,而不是嵌套它们。

表明可能误解规范的错误

有时,某些东西被禁止是因为允许它很可能会导致作者困惑。

例如,将 disabled 属性设置为值 "false" 是不允许的,因为尽管看起来意思是元素已启用,但实际上意味着元素是 *禁用的*(对于实现来说,重要的是属性的存在,而不是它的值)。

涉及仅仅为了简化语言而强加的限制的错误

一些符合性错误简化了作者需要学习的语言。

例如,area 元素的 shape 属性,尽管在实践中接受了 circcircle 作为同义词,但它不允许使用 circ 值,以便简化教程和其他学习辅助工具。允许两者都没有好处,但它会在教授语言时造成额外的混淆。

涉及解析器特性的错误

某些元素以稍微古怪的方式解析(通常出于历史原因),并且它们的内容模型限制旨在避免将作者暴露给这些问题。

例如,form 元素不允许在 短语内容 中使用,因为当作为 HTML 解析时,form 元素的开始标记将隐式地表示 p 元素的结束标记。因此,以下标记会产生两个 段落,而不是一个

<p>Welcome. <form><label>Name:</label> <input></form>

它与以下内容的解析方式完全相同

<p>Welcome. </p><form><label>Name:</label> <input></form>
可能导致脚本以难以调试的方式失败的错误

一些错误旨在帮助防止脚本问题,这些问题很难调试。

这就是为什么例如,拥有两个具有相同值的 id 属性是非符合性的。重复的 ID会导致选择错误的元素,有时会产生灾难性的影响,其原因很难确定。

浪费创作时间的错误

某些构造被禁止,因为历史上它们是造成大量创作时间浪费的原因,通过鼓励作者避免创建它们,作者可以在未来的工作中节省时间。

例如,script 元素的 src 属性会导致元素的内容被忽略。但是,这并不明显,特别是如果元素的内容看起来是可执行脚本——这会导致作者花费大量时间尝试调试内联脚本,而没有意识到它没有执行。为了减少这个问题,本规范规定在 script 元素中,当存在 src 属性时,使用可执行脚本是非符合性的。这意味着验证其文档的作者不太可能在这种错误上浪费时间。

涉及影响作者在 HTML 和 XML 语法之间迁移的领域的错误

一些作者喜欢编写可以被解释为 XML 和 HTML,并获得类似结果的文件。尽管一般不鼓励这种做法,因为涉及许多微妙的复杂性(尤其是在涉及脚本、样式或任何类型的自动序列化时),但本规范有一些限制旨在至少在一定程度上减轻这些困难。这使得作者在 HTML 和 XML 语法之间迁移时更容易将其用作过渡步骤。

例如,围绕 langxml:lang 属性有一些复杂的规则,旨在使两者保持同步。

另一个例子是 HTML 序列化中 xmlns 属性值的限制,这些限制旨在确保符合文档中的元素无论作为 HTML 还是 XML 处理都位于相同的命名空间中。

涉及为未来扩展保留的领域的错误

与旨在允许在语言的未来修订中使用新语法的语法限制一样,元素的内容模型和属性值的某些限制旨在允许将来扩展 HTML 词汇表。

例如,将 target 属性的值限制为以 U+005F 下划线 (_) 开头的特定预定义值,允许将来引入新的预定义值,而不会与作者定义的值冲突。

表明其他规范的错误使用方式的错误

某些限制旨在支持其他规范做出的限制。

例如,要求使用媒体查询列表的属性仅使用 *有效的* 媒体查询列表,这加强了遵循该规范的符合性规则的重要性。

1.11 建议阅读

以下文档可能对本规范的读者感兴趣。

万维网 1.0 字符模型:基础知识 [CHARMOD]

本体系结构规范为规范作者、软件开发人员和内容开发人员提供了一个共同的参考,用于在万维网上进行可互操作的文本操作,它基于 Unicode 标准和 ISO/IEC 10646 联合定义的通用字符集。讨论的主题包括“字符”、“编码”和“字符串”的术语使用、参考处理模型、字符编码的选择和识别、字符转义和字符串索引。

Unicode 安全注意事项 [UTR36]

由于 Unicode 包含如此大量的字符,并融合了世界各地不同的书写系统,因此不正确的使用可能会使程序或系统暴露于可能的安全攻击。随着越来越多的产品被国际化,这一点尤为重要。本文档描述了程序员、系统分析师、标准制定者和用户应考虑的一些安全注意事项,并提供了一些具体建议以降低出现问题的风险。

Web 内容无障碍指南 (WCAG) [WCAG]

Web 内容无障碍指南 (WCAG) 涵盖了使 web 内容更易访问的广泛建议。遵循这些指南将使内容更容易被更多有残疾的人访问,包括失明和低视力、失聪和听力损失、学习障碍、认知障碍、行动不便、言语障碍、光敏感和这些残疾的组合。遵循这些指南通常也会使您的 web 内容对一般用户更易用。