动态标准 — 最后更新于 2024年9月12日
本节仅描述标记为 HTML MIME 类型 的资源的规则。XML 资源的规则在下面标题为 "XML 语法" 的部分中讨论。
本节仅适用于文档、创作工具和标记生成器。特别是,它不适用于一致性检查器;一致性检查器必须使用下一节(“解析 HTML 文档”)中给出的要求。
文档必须包含以下部分,按给定顺序排列
html
元素的形式。上面提到的各种内容类型在接下来的几节中进行了描述。
此外,对 字符编码声明 的序列化方式也有一些限制,如关于该主题的部分所述。
ASCII 空格 在 html
元素之前,在 html
元素的开头以及在 head
元素之前,将在文档解析时被删除;ASCII 空格 在 html
元素之后 将被解析,就好像它在 body
元素的末尾一样。因此,ASCII 空格 在 文档元素 周围不会往返。
建议在 DOCTYPE 之后,在文档元素之前的任何注释之后,在 html
元素的开始标签之后(如果它没有 省略),以及在 html
元素内部但在 head
元素之前的任何注释之后插入换行符。
HTML 语法中的许多字符串(例如元素及其属性的名称)不区分大小写,但仅限于 ASCII 大写字母 和 ASCII 小写字母。为方便起见,在本节中,这仅称为“不区分大小写”。
DOCTYPE 是一个必需的前言。
由于遗留原因,需要使用 DOCTYPE。当省略时,浏览器倾向于使用与某些规范不兼容的不同渲染模式。在文档中包含 DOCTYPE 可确保浏览器尽最大努力遵循相关规范。
DOCTYPE 必须包含以下组件,按此顺序排列
<!DOCTYPE
”进行 ASCII 不区分大小写 匹配的字符串。html
”进行 ASCII 不区分大小写 匹配的字符串。换句话说,<!DOCTYPE html>
,不区分大小写。
为了能够输出不包含短 DOCTYPE“<!DOCTYPE html>
”的 HTML 标记的 HTML 生成器,可以将 DOCTYPE 遗留字符串 插入到 DOCTYPE 中(在上面定义的位置)。此字符串必须包含
SYSTEM
”进行 ASCII 不区分大小写 匹配的字符串。about:legacy-compat
”。换句话说,<!DOCTYPE html SYSTEM "about:legacy-compat">
或 <!DOCTYPE html SYSTEM 'about:legacy-compat'>
,除了单引号或双引号中的部分之外,其他部分都不区分大小写。
除非文档是从无法输出较短字符串的系统生成的,否则不应使用 DOCTYPE 遗留字符串。
有六种不同的 元素:空元素、template
元素、原始文本元素、可转义原始文本元素、外来元素 和 普通元素。
area
、base
、br
、col
、embed
、hr
、img
、input
、link
、meta
、source
、track
、wbr
template
元素template
script
、style
textarea
、title
标签 用于在标记中分隔元素的开始和结束。 原始文本、可转义原始文本 和 普通 元素都有一个 开始标签 来指示它们的开始位置,以及一个 结束标签 来指示它们的结束位置。某些 普通元素 的开始和结束标签可以 省略,如下面关于 可选标签 的部分所述。那些不能省略的必须不能省略。 空元素 只有一个开始标签;空元素 必须不能指定结束标签。 外来元素 必须要么具有开始标签和结束标签,要么具有标记为自闭合的开始标签,在这种情况下,它们必须不能具有结束标签。
元素的 内容 必须放置在紧接开始标签之后(在某些情况下 可能隐含)和紧接结束标签之前(同样,在某些情况下 可能隐含)。每个单独元素的确切允许内容取决于该元素的 内容模型,如本规范前面所述。元素必须不能包含其内容模型不允许的内容。但是,除了这些内容模型对内容施加的限制之外,五种类型的元素还有其他语法 要求。
空元素 不能有任何内容(因为没有结束标签,所以不能在开始标签和结束标签之间放置任何内容)。
template
元素 可以包含 模板内容,但此类 模板内容 不是 template
元素本身的子元素。相反,它们存储在一个与不同 Document
(没有 浏览上下文)关联的 DocumentFragment
中,以避免 template
内容干扰主 Document
。 模板内容 的标记放置在 template
元素的开始标签之后,以及 template
元素的结束标签之前(与其他元素相同),并且可以包含任何 文本、字符引用、元素 和 注释,但文本不能包含字符 U+003C LESS-THAN SIGN (<) 或 模棱两可的 &。
可转义原始文本元素 可以包含 文本 和 字符引用,但文本不能包含 模棱两可的 &。下面还描述了 其他限制。
外来元素 其开始标签标记为自闭合的,不能有任何内容(因为,再次强调,由于没有结束标签,所以无法在开始标签和结束标签之间放置任何内容)。外来元素 其开始标签未标记为自闭合的,可以包含 文本、字符引用、CDATA 区段、其他 元素 和 注释,但文本不能包含字符 U+003C LESS-THAN SIGN (<) 或 模棱两可的 &。
HTML 语法不支持命名空间声明,即使在 外来元素 中也不支持。
例如,考虑以下 HTML 片段
< p >
< svg >
< metadata >
<!-- this is invalid -->
< cdr:license xmlns:cdr = "https://www.example.com/cdr/metadata" name = "MIT" />
</ metadata >
</ svg >
</ p >
最里面的元素 cdr:license
实际上位于 SVG 命名空间中,因为“xmlns:cdr
”属性无效(与 XML 不同)。事实上,如上文片段中的注释所说,该片段实际上不符合规范。这是因为 SVG 2 未在 SVG 命名空间中定义任何名为“cdr:license
”的元素。
普通元素 可以包含 文本、字符引用、其他 元素 和 注释,但文本不能包含字符 U+003C LESS-THAN SIGN (<) 或 模棱两可的 &。一些 普通元素 对其允许包含的内容还有 更多限制,这超出了内容模型强加的限制以及本段中描述的限制。这些限制将在下面描述。
标签包含一个 标签名称,用于提供元素的名称。HTML 元素的名称都只使用 ASCII 字母数字字符。在 HTML 语法中,标签名称,即使是 外来元素 的标签名称,也可以使用任何大小写字母的组合来编写,只要将其转换为全小写后与元素的标签名称匹配即可;标签名称不区分大小写。
开始标签 必须具有以下格式
结束标签 必须具有以下格式
属性 用于在元素的开始标签内表达。
属性具有名称和值。属性名称 必须由一个或多个字符组成,这些字符不包括 控制字符、U+0020 SPACE、U+0022 (")、U+0027 (')、U+003E (>)、U+002F (/)、U+003D (=) 和 非字符。在 HTML 语法中,属性名称,即使是 外来元素 的属性名称,也可以使用任何 ASCII 小写 和 ASCII 大写字母 的组合来编写。
属性值 是 文本 和 字符引用 的混合,但附加限制是文本不能包含 模棱两可的 &。
属性可以用四种不同的方式指定
仅 属性名称。该值隐式为空字符串。
在以下示例中,disabled
属性使用空属性语法给出
< input disabled >
如果使用空属性语法的属性后面要跟另一个属性,则这两个属性之间必须有 ASCII 空格 分隔。
属性名称,后跟零个或多个 ASCII 空格,后跟单个 U+003D EQUALS SIGN 字符,后跟零个或多个 ASCII 空格,后跟 属性值,除了上面为属性值给出的要求外,还必须不包含任何文字 ASCII 空格、任何 U+0022 QUOTATION MARK 字符 (")、U+0027 APOSTROPHE 字符 (')、U+003D EQUALS SIGN 字符 (=)、U+003C LESS-THAN SIGN 字符 (<)、U+003E GREATER-THAN SIGN 字符 (>) 或 U+0060 GRAVE ACCENT 字符 (`),并且不能是空字符串。
在以下示例中,value
属性使用未加引号的属性值语法给出
< input value = yes >
如果使用未加引号的属性值语法的属性后面要跟另一个属性或上面 开始标签 语法步骤 6 中允许的可选 U+002F SOLIDUS 字符 (/),则这两个之间必须有 ASCII 空格 分隔。
属性名称,后跟零个或多个 ASCII 空格,后跟单个 U+003D EQUALS SIGN 字符,后跟零个或多个 ASCII 空格,后跟单个 U+0027 APOSTROPHE 字符 ('),后跟 属性值,除了上面为属性值给出的要求外,还必须不包含任何文字 U+0027 APOSTROPHE 字符 ('),最后再跟一个第二个单个 U+0027 APOSTROPHE 字符 (')。
在以下示例中,type
属性使用单引号属性值语法给出
< input type = 'checkbox' >
如果使用单引号属性值语法的属性后面要跟另一个属性,则这两个属性之间必须有 ASCII 空格 分隔。
属性名称 (attribute name),后面跟着零个或多个 ASCII 空格字符,后面跟着一个 U+003D 等号字符,后面跟着零个或多个 ASCII 空格字符,后面跟着一个 U+0022 双引号字符 ("),后面跟着 属性值,除了上面给出的属性值的额外要求外,属性值中不能包含任何字面量 U+0022 双引号字符 ("),最后跟着第二个 U+0022 双引号字符 (")。
在下面的示例中,name
属性使用双引号属性值语法给出。
< input name = "be evil" >
如果使用双引号属性语法的属性后面要跟着另一个属性,则这两个属性之间必须有 ASCII 空格字符 分隔。
同一个开始标签上永远不能有两个或多个属性,它们的名称是彼此的 ASCII 不区分大小写 匹配。
当 外来元素 的名称与以下表格中某一行的第一列和第二列(本地名称和命名空间)指定的命名空间属性相同,则必须使用该行第三列指定的名称来书写该属性。
本地名称 | 命名空间 | 属性名称 |
---|---|---|
actuate | XLink 命名空间 | xlink:actuate
|
arcrole | XLink 命名空间 | xlink:arcrole
|
href | XLink 命名空间 | xlink:href
|
role | XLink 命名空间 | xlink:role
|
show | XLink 命名空间 | xlink:show
|
title | XLink 命名空间 | xlink:title
|
type | XLink 命名空间 | xlink:type
|
lang | XML 命名空间 | xml:lang
|
space | XML 命名空间 | xml:space
|
xmlns | XMLNS 命名空间 | xmlns
|
xlink | XMLNS 命名空间 | xmlns:xlink
|
其他命名空间属性都不能用 HTML 语法 表示。
以上表格中的属性是否符合规范由其他规范定义(例如 SVG 2 和 MathML);本节仅描述如果使用 HTML 语法序列化这些属性的语法规则。
某些标签可以 省略。
在下面描述的情况下,省略元素的 开始标签 并不意味着元素不存在;它是隐含的,但仍然存在。例如,HTML 文档始终具有一个根 html
元素,即使字符串 <html>
在标记中任何地方都没有出现。
html
元素的 开始标签 可以省略,如果 html
元素内部的第一件事不是 注释。
例如,在以下情况下,可以移除 "<html>
" 标签
<!DOCTYPE HTML>
< html >
< head >
< title > Hello</ title >
</ head >
< body >
< p > Welcome to this example.</ p >
</ body >
</ html >
这样做会使文档看起来像这样
<!DOCTYPE HTML>
< head >
< title > Hello</ title >
</ head >
< body >
< p > Welcome to this example.</ p >
</ body >
</ html >
这具有完全相同的 DOM。特别是,请注意,解析器会忽略 文档元素 周围的空格。以下示例也将具有完全相同的 DOM
<!DOCTYPE HTML> < head >
< title > Hello</ title >
</ head >
< body >
< p > Welcome to this example.</ p >
</ body >
</ html >
但是,在下面的示例中,移除开始标签会将注释移动到 html
元素之前。
<!DOCTYPE HTML>
< html >
<!-- where is this comment in the DOM? -->
< head >
< title > Hello</ title >
</ head >
< body >
< p > Welcome to this example.</ p >
</ body >
</ html >
移除标签后,文档实际上变成了与以下内容相同的内容
<!DOCTYPE HTML>
<!-- where is this comment in the DOM? -->
< html >
< head >
< title > Hello</ title >
</ head >
< body >
< p > Welcome to this example.</ p >
</ body >
</ html >
这就是为什么只有在标签后面没有注释时才能移除该标签:在有注释的情况下移除该标签会更改文档的生成的解析树。当然,如果注释的位置无关紧要,则可以省略该标签,就像注释已首先移动到开始标签之前一样。
html
元素的 结束标签 可以省略,如果 html
元素后面没有紧跟着 注释。
head
元素的 开始标签 可以省略,如果该元素为空,或者 head
元素内部的第一件事是元素。
head
元素的 结束标签 可以省略,如果 head
元素后面没有紧跟着 ASCII 空格字符 或 注释。
body
元素的 开始标签 可以省略,如果该元素为空,或者 body
元素内部的第一件事不是 ASCII 空格字符 或 注释,除非 body
元素内部的第一件事是 meta
、noscript
、link
、script
、style
或 template
元素。
body
元素的 结束标签 可以省略,如果 body
元素后面没有紧跟着 注释。
请注意,在上面的示例中,head
元素的开始和结束标签以及 body
元素的开始标签不能省略,因为它们被空格包围。
<!DOCTYPE HTML>
< html >
< head >
< title > Hello</ title >
</ head >
< body >
< p > Welcome to this example.</ p >
</ body >
</ html >
(body
和 html
元素的结束标签可以毫无问题地省略;这些标签之后的任何空格都会被解析到 body
元素中。)
但是,通常情况下,空格不是问题。如果我们首先移除我们不关心的空格
<!DOCTYPE HTML> < html >< head >< title > Hello</ title ></ head >< body >< p > Welcome to this example.</ p ></ body ></ html >
然后我们可以省略一些标签而不会影响 DOM
<!DOCTYPE HTML> < title > Hello</ title >< p > Welcome to this example.</ p >
此时,我们还可以添加一些空格
<!DOCTYPE HTML>
< title > Hello</ title >
< p > Welcome to this example.</ p >
这将等同于此文档,其中省略的标签显示在其解析器隐含的位置;由此产生的唯一空格文本节点是 head
元素末尾的换行符。
<!DOCTYPE HTML>
< html >< head > < title > Hello</ title >
</ head >< body > < p > Welcome to this example.</ p > </ body ></ html >
li
元素的 结束标签 可以省略,如果 li
元素后面紧跟着另一个 li
元素,或者父元素中没有更多内容。
dt
元素的 结束标签 可以省略,如果 dt
元素后面紧跟着另一个 dt
元素或 dd
元素。
dd
元素的 结束标签 可以省略,如果 dd
元素后面紧跟着另一个 dd
元素或 dt
元素,或者父元素中没有更多内容。
p
元素的 结束标签 可以省略,如果 p
元素后面紧跟着 address
、article
、aside
、blockquote
、details
、dialog
、div
、dl
、fieldset
、figcaption
、figure
、footer
、form
、h1
、h2
、h3
、h4
、h5
、h6
、header
、hgroup
、hr
、main
、menu
、nav
、ol
、p
、pre
、search
、section
、table
或 ul
元素,或者父元素中没有更多内容,并且父元素是 HTML 元素,而不是 a
、audio
、del
、ins
、map
、noscript
或 video
元素,或者 自治自定义元素。
因此,我们可以进一步简化前面的示例
<!DOCTYPE HTML> < title > Hello</ title >< p > Welcome to this example.
如果`rt
` 元素紧跟着一个`rt
` 或 `rp
` 元素,或者父元素中没有更多内容,则可以省略其`结束标签`。
如果`rp
` 元素紧跟着一个`rt
` 或 `rp
` 元素,或者父元素中没有更多内容,则可以省略其`结束标签`。
如果`optgroup
` 元素紧跟着另一个`optgroup
` 元素,或者紧跟着一个`hr
` 元素,或者父元素中没有更多内容,则可以省略其`结束标签`。
如果`option
` 元素紧跟着另一个`option
` 元素,或者紧跟着一个`optgroup
` 元素,或者紧跟着一个`hr
` 元素,或者父元素中没有更多内容,则可以省略其`结束标签`。
如果`colgroup
` 元素内部的第一个元素是`col
` 元素,并且该元素前面不紧跟着另一个`colgroup
` 元素(其`结束标签` 已被省略),则可以省略其`开始标签`。(如果该元素为空,则不能省略。)
如果`colgroup
` 元素后面不紧跟着ASCII 空格 或 `注释`,则可以省略其`结束标签`。
如果`caption
` 元素后面不紧跟着ASCII 空格 或 `注释`,则可以省略其`结束标签`。
如果`thead
` 元素紧跟着`tbody
` 或 `tfoot
` 元素,则可以省略其`结束标签`。
如果`tbody
` 元素内部的第一个元素是`tr
` 元素,并且该元素前面不紧跟着`tbody
`、`thead
` 或 `tfoot
` 元素(其`结束标签` 已被省略),则可以省略其`开始标签`。(如果该元素为空,则不能省略。)
如果`tbody
` 元素紧跟着`tbody
` 或 `tfoot
` 元素,或者父元素中没有更多内容,则可以省略其`结束标签`。
如果父元素中没有更多内容,则可以省略`tfoot
` 元素的`结束标签`。
如果`tr
` 元素紧跟着另一个`tr
` 元素,或者父元素中没有更多内容,则可以省略其`结束标签`。
如果`td
` 元素紧跟着`td
` 或 `th
` 元素,或者父元素中没有更多内容,则可以省略其`结束标签`。
如果`th
` 元素紧跟着`td
` 或 `th
` 元素,或者父元素中没有更多内容,则可以省略其`结束标签`。
省略所有这些与表格相关的标签的能力使表格标记更加简洁。
以这个例子为例
< table >
< caption > 37547 TEE Electric Powered Rail Car Train Functions (Abbreviated)</ caption >
< colgroup >< col >< col >< col ></ colgroup >
< thead >
< tr >
< th > Function</ th >
< th > Control Unit</ th >
< th > Central Station</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td > Headlights</ td >
< td > ✔</ td >
< td > ✔</ td >
</ tr >
< tr >
< td > Interior Lights</ td >
< td > ✔</ td >
< td > ✔</ td >
</ tr >
< tr >
< td > Electric locomotive operating sounds</ td >
< td > ✔</ td >
< td > ✔</ td >
</ tr >
< tr >
< td > Engineer's cab lighting</ td >
< td ></ td >
< td > ✔</ td >
</ tr >
< tr >
< td > Station Announcements - Swiss</ td >
< td ></ td >
< td > ✔</ td >
</ tr >
</ tbody >
</ table >
除了某些空格差异外,完全相同的表格可以用以下方式标记:
< table >
< caption > 37547 TEE Electric Powered Rail Car Train Functions (Abbreviated)
< colgroup >< col >< col >< col >
< thead >
< tr >
< th > Function
< th > Control Unit
< th > Central Station
< tbody >
< tr >
< td > Headlights
< td > ✔
< td > ✔
< tr >
< td > Interior Lights
< td > ✔
< td > ✔
< tr >
< td > Electric locomotive operating sounds
< td > ✔
< td > ✔
< tr >
< td > Engineer's cab lighting
< td >
< td > ✔
< tr >
< td > Station Announcements - Swiss
< td >
< td > ✔
</ table >
由于单元格以这种方式占据的空间更少,因此可以通过将每一行放在一行上来使它变得更加简洁
< table >
< caption > 37547 TEE Electric Powered Rail Car Train Functions (Abbreviated)
< colgroup >< col >< col >< col >
< thead >
< tr > < th > Function < th > Control Unit < th > Central Station
< tbody >
< tr > < td > Headlights < td > ✔ < td > ✔
< tr > < td > Interior Lights < td > ✔ < td > ✔
< tr > < td > Electric locomotive operating sounds < td > ✔ < td > ✔
< tr > < td > Engineer's cab lighting < td > < td > ✔
< tr > < td > Station Announcements - Swiss < td > < td > ✔
</ table >
在 DOM 级别,这些表格之间的唯一区别在于(无论如何,在语义上都是中性的)空格的确切位置。
**但是**,如果`开始标签` 具有任何属性,则绝不能省略。
回到前面那个去掉了所有空格,然后去掉了所有可选标签的例子
<!DOCTYPE HTML> < title > Hello</ title >< p > Welcome to this example.
如果此示例中的`body
` 元素必须具有`class
` 属性,并且`html
` 元素必须具有`lang
` 属性,则标记必须变为
<!DOCTYPE HTML> < html lang = "en" >< title > Hello</ title >< body class = "demo" >< p > Welcome to this example.
本节假设文档符合规范,特别是没有违反`内容模型`。在不符合本规范中描述的`内容模型` 的文档中,以本节中描述的方式省略标签可能会导致意外的 DOM 差异(这在一定程度上是内容模型旨在避免的)。
出于历史原因,某些元素除了其内容模型给出的限制之外,还有额外的限制。
`table
` 元素不能包含`tr
` 元素,即使根据本规范中描述的内容模型,这些元素在技术上允许在`table
` 元素内部。(如果在标记中将`tr
` 元素放在`table
` 内部,它实际上会在其前面隐含一个`tbody
` 开始标签。)
可以在`pre
` 和 `textarea
` 元素的`开始标签` 后面紧跟着放置一个`换行符`。这不会影响元素的处理。如果元素的内容本身以`换行符` 开头,则必须包含否则可选的`换行符`(因为否则内容中的前导换行符将被视为可选换行符,并被忽略)。
`原始文本` 和 `可转义原始文本元素` 中的文本不得包含任何“`</`”(U+003C 小于号、U+002F 斜杠)字符串,后跟与元素的标签名称不区分大小写匹配的字符,以及 U+0009 字符制表符(制表符)、U+000A 换行符(LF)、U+000C 换页符(FF)、U+000D 回车符(CR)、U+0020 空格、U+003E 大于号(>)或 U+002F 斜杠(/)之一。
在元素、属性值和注释中允许`文本`。根据文本的放置位置,对文本中允许和不允许的内容施加额外的约束,如其他部分所述。
HTML 中的`换行符` 可以表示为 U+000D 回车符 (CR) 字符、U+000A 换行符 (LF) 字符,或者按此顺序排列的 U+000D 回车符 (CR)、U+000A 换行符 (LF) 字符对。
在允许`字符引用` 的地方,U+000A 换行符 (LF) 字符(但不是 U+000D 回车符 (CR) 字符)的字符引用也表示`换行符`。
在其他部分描述的某些情况下,`文本` 可以与`字符引用` 混合使用。这些可以用来转义在`文本` 中原本不允许包含的字符。
字符引用必须以 U+0026 与号 (&) 字符开头。在此之后,有三种可能的字符引用类型
上面描述的数字字符引用形式允许引用任何代码点,但 U+000D CR、非字符 和控制字符(除了ASCII 空格)除外。
一个模棱两可的 & 符号 是一个 U+0026 & 符号字符 (&),后面跟着一个或多个ASCII 字母数字字符,后面跟着一个 U+003B 分号字符 (;),其中这些字符与命名字符引用部分给出的任何名称都不匹配。
CDATA 区段必须包含以下组件,按此顺序
<![CDATA[
”。]]>
”。]]>
”。CDATA 区段只能用于外部内容(MathML 或 SVG)。在此示例中,CDATA 区段用于转义MathML ms
元素的内容
< p > You can add a string to a number, but this stringifies the number:</ p >
< math >
< ms > <![CDATA[x<y]]> </ ms >
< mo > +</ mo >
< mn > 3</ mn >
< mo > =</ mo >
< ms > <![CDATA[x<y3]]> </ ms >
</ math >
注释必须具有以下格式
<!--
”。>
”开头,也不能以字符串“->
”开头,也不能包含字符串“<!--
”、“-->
”或“--!>
”,也不能以字符串“<!-
”结尾。-->
”。该文本允许以字符串“<!
”结尾,例如 <!--My favorite operators are > and <!-->
。