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

1 简介

1.1 此规范的位置

此规范详细定义了网络平台的重要组成部分。它在网络平台规范栈中相对于其他规范的位置可以概括如下

CSS SVG MathML Service Workers IDB Fetch CSP AV1 Opus PNG THIS SPECIFICATION HTTP TLS DOM Unicode Web IDL MIME URL XML JavaScript Encoding

1.2 这是 HTML5 吗?

本节为非规范性内容。

简而言之:是。

详细解释:“HTML5”一词被广泛用作流行语来指代现代网络技术,其中许多技术(尽管并非全部)是在 WHATWG 开发的。本文档就是其中之一;其他文档可从 WHATWG 标准概述 获得。

1.3 背景

本节为非规范性内容。

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

1.4 受众

本节为非规范性内容。

此规范面向使用此规范中定义的功能的文档和脚本的作者,以及对使用此规范中定义的功能的页面进行操作的工具的实现者,以及希望根据此规范的要求确定文档或实现的正确性的个人。

对于那些不熟悉网络技术的人来说,此文档可能不适合阅读,因为它在某些地方牺牲了清晰度以追求准确性,牺牲了简洁性以追求完整性。更易于理解的教程和创作指南可以提供更温和的介绍。

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

1.5 范围

本节为非规范性内容。

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

此规范的范围不包括提供针对特定媒体的呈现自定义机制(尽管此规范末尾包含了针对网络浏览器的默认呈现规则,并且作为语言的一部分提供了多种用于连接到 CSS 的机制)。

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

1.6 历史

本节为非规范性内容。

在最初的五年(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 年结束)的名义发布。这些工作随后停滞不前,2004 年发布了一些 DOM Level 3 规范,但工作组在所有 Level 3 草案完成之前就被关闭了。

2003 年,XForms 的发布,一种被定位为下一代网络表单的技术,激发了人们对发展 HTML 本身,而不是寻找其替代品的兴趣。这种兴趣源于人们认识到 XML 作为网络技术的部署仅限于全新的技术(如 RSS 和后来的 Atom),而不是作为现有部署技术的替代品(如 HTML)。

一项概念验证表明,可以扩展 HTML4 的表单以提供 XForms 1.0 引入的许多功能,而无需要求浏览器实现与现有 HTML 网页不兼容的呈现引擎,这是这种重新燃起的兴趣的第一个成果。在此早期阶段,虽然草案已公开提供,并且已从所有来源征求意见,但规范仅在 Opera Software 的版权下。

在 2004 年的一次 W3C 研讨会上测试了重新开放 HTML 发展的想法,在该研讨会上,Mozilla 和 Opera 共同向 W3C 展示了构成 HTML5 工作的基础的一些原则(如下所述),以及上述仅涵盖表单相关功能的早期草案提案。该提案遭到拒绝,理由是该提案与之前为网络发展选择的路线相冲突;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.7 设计说明

本节为非规范性内容。

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

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

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

尽管有所有这些,但已经努力遵循某些设计目标。这些将在接下来的几个小节中进行描述。

1.7.1 脚本执行的可序列化性

本节为非规范性内容。

为了避免让网络作者接触到多线程的复杂性,HTML 和 DOM API 的设计使得任何脚本都无法检测到其他脚本的同步执行。即使使用 工作线程,也希望实现的行为可以被认为是完全序列化了所有全局中的所有脚本的执行。

这种一般设计原则的例外是 JavaScript SharedArrayBuffer 类。使用 SharedArrayBuffer 对象,实际上可以观察到其他 代理 中的脚本正在同步执行。此外,由于 JavaScript 内存模型,存在一些情况不仅无法通过序列化 *脚本* 执行来表示,而且也无法通过那些脚本之间的序列化 *语句* 执行来表示。

1.7.2 与其他规范的兼容性

本节为非规范性内容。

本规范与其他众多规范进行交互并依赖于它们。不幸的是,在某些情况下,冲突的需求导致本规范违反了这些其他规范的要求。在出现这种情况时,每项违规行为均已标注为“故意违规”,并且已注明违规原因。

1.7.3 可扩展性

本节为非规范性内容。

HTML 拥有广泛的可扩展机制,可用于以安全方式添加语义

1.8 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.9 本规范的结构

本节为非规范性内容。

本规范分为以下几个主要部分

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

还有一些附录,列出了 过时的功能IANA 注意事项 以及一些索引。

1.9.1 如何阅读本规范

本规范应像所有其他规范一样阅读。首先,应将其完整阅读多次。然后,应将其反向阅读至少一次。然后,应通过从内容列表中随机选择部分并跟踪所有交叉引用来阅读它。

正如下面的一致性要求部分所述,本规范描述了针对各种一致性类别的符合性标准。特别是,有一些符合性要求适用于生产者,例如作者及其创建的文档,还有一些符合性要求适用于消费者,例如 Web 浏览器。它们可以通过它们要求的内容来区分:对生产者的要求规定了允许的内容,而对消费者的要求规定了软件的行为方式。

例如,“foo 属性的值必须是一个 有效的整数”是对生产者的要求,因为它规定了允许的值;相比之下,要求“foo 属性的值必须使用 解析整数的规则 进行解析”是对消费者的要求,因为它描述了如何处理内容。

对生产者的要求对消费者没有任何影响。

继续以上示例,要求特定属性的值被限制为 有效的整数 绝不暗示任何关于对消费者的要求。可能是消费者实际上被要求将该属性视为不透明字符串,完全不受其值是否符合要求的影响。也可能是(如前例所示)消费者被要求使用特定规则解析该值,这些规则定义了如何处理无效(在本例中为非数字)值。

1.9.2 排版约定

这是一个定义、要求或说明。

这是一个注释。

这是一个示例。

这是一个开放性问题。

这是一个警告。

[Exposed=Window]
interface Example {
  // this is an IDL definition
};
variable = object.method([optionalArgument])

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

/* this is a CSS fragment */

术语的定义实例用 这种方式 标记。对该术语的用法用 这种方式这种方式 标记。

元素、属性或 API 的定义实例用 这种方式 标记。对该元素、属性或 API 的引用用 这种方式 标记。

其他代码片段用 这种方式 标记。

变量用 这种方式 标记。

在算法中, 同步部分 中的步骤用 ⌛ 标记。

在某些情况下,要求以包含条件和对应要求的列表形式给出。在这种情况下,适用于条件的要求始终是紧随条件的第一组要求,即使这些要求有多个条件集也是如此。此类情况按如下方式显示

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

1.10 关于 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 用户代理(例如,网页浏览器)然后解析此标记,将其转换为 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 文档时表示 HTML 文档的方式,因此本规范主要以 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.10.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.10.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.10.3 如何在编写 HTML 时捕获错误:验证器和一致性检查器

本节为非规范性内容。

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

1.11 作者的一致性要求

本节为非规范性内容。

与 HTML 规范的先前版本不同,本规范详细定义了对无效文档和有效文档的必需处理。

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

1.11.1 表现性标记

本节为非规范性内容。

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

使用表现性元素会导致更差的无障碍性。

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

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

更高的维护成本。

维护以标记独立于样式的方式编写的网站要容易得多。例如,更改使用`<font color="">` 的网站的颜色需要在整个网站范围内进行更改,而对基于 CSS 的网站进行类似更改只需要更改单个文件。

更大的文档大小。

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

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

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

还值得注意的是,一些以前是表现性的元素在本规范中重新定义为独立于媒体的:`b`、`i`、`hr`、`s`、`small`和`u`。

1.11.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 重音符(`)字符。在某些旧版用户代理中,它有时会被视为引号字符。

另一个例子是 DOCTYPE,它需要触发 非怪癖模式,因为旧版用户代理在 怪癖模式中的行为通常是大量未记录的。

可能使作者面临安全攻击的错误

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

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

作者意图不明确的情况

作者意图非常不明确的标记通常会被标记为不符合标准。尽早纠正这些错误可以简化后续维护。

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

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

当用户犯了一个简单的打字错误时,如果能够尽早捕获该错误,将非常有用,因为这可以为作者节省大量的调试时间。因此,本规范通常认为使用与本规范中定义的名称不匹配的元素名称、属性名称等是错误的。

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

可能影响未来新语法的错误

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

例如,结束标签中的“属性”目前被忽略,但它们是无效的,以防语言的未来更改使用该语法功能,而不会与已部署(且有效!)的内容冲突。

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

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

本节为非规范性内容。

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

涉及语义可疑内容的错误

为了避免滥用具有定义意义的元素,定义了内容模型,限制了元素在嵌套时可以如何嵌套,而这些嵌套将毫无价值。

例如,本规范禁止在 kbd 元素内嵌套 section 元素,因为作者极不可能表明整个部分应该被键入。

涉及表达语义冲突的错误

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

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

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

另一个例子是对 ul 元素的内容模型的限制,它只允许 li 元素子元素。列表的定义仅仅是零个或多个列表项,因此,如果一个 ul 元素包含 li 元素以外的任何内容,则不清楚作者的意图。

默认样式可能导致混淆的情况

某些元素具有默认样式或行为,这些样式或行为使某些组合很可能导致混淆。如果这些组合有等效的替代方案,而没有此问题,则不允许使用这些混淆的组合。

例如,div 元素被渲染为 块级框span 元素被渲染为 行内框。将 块级框 放入 行内框 中是不必要的混淆;由于仅嵌套 div 元素,或仅嵌套 span 元素,或嵌套 span 元素到 div 元素中,都与将 div 元素嵌套到 span 元素中具有相同的目的,但只有后者涉及 块级框行内框 中,因此不允许后者组合。

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

表明可能误解规范的错误

有时,某些东西被禁止是因为允许它很可能会造成作者的混淆。

例如,将 disabled 属性设置为值“false”被禁止,因为尽管它看起来意味着该元素已启用,但实际上它意味着该元素已被禁用(对实现而言重要的是属性的存在,而不是它的值)。

涉及仅仅为了简化语言而实施的限制的错误

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

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

涉及解析器特性的错误

某些元素的解析方式有些古怪(通常是出于历史原因),它们的 content model 限制旨在避免作者遇到这些问题。

例如,不允许在 短语内容 中使用 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 词汇表。

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

表明其他规范使用不当的错误

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

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

1.12 建议阅读

本节为非规范性内容。

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

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

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

Unicode 安全注意事项 [UTR36]

由于 Unicode 包含如此大量的字符并包含世界各地的各种书写系统,因此使用不当可能会使程序或系统面临潜在的安全攻击。随着越来越多的产品被国际化,这一点尤其重要。本文档描述了程序员、系统分析师、标准开发人员和用户应考虑的一些安全注意事项,并提供了一些具体建议来降低问题的风险。

Web 内容可访问性指南 (WCAG) [WCAG]

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

创作工具可访问性指南 (ATAG) 2.0 [ATAG]

本规范为设计更适合残疾人使用的 web 内容创作工具提供了指南。符合这些指南的创作工具将通过为有残疾的作者提供可访问的用户界面以及通过启用、支持和促进所有作者创建可访问的 web 内容来促进可访问性。

用户代理可访问性指南 (UAAG) 2.0 [UAAG]

本文档为设计用户代理提供了指南,这些用户代理降低了残疾人访问 web 的障碍。用户代理包括浏览器和其他类型的检索和呈现 web 内容的软件。符合这些指南的用户代理将通过其自身的用户界面以及其他内部设施来促进可访问性,包括其与其他技术(尤其是辅助技术)通信的能力。此外,所有用户,而不仅仅是有残疾的用户,都应发现符合规范的用户代理更易用。