26

显然,如果您</p>的元素中有一个结束标签而没有匹配的开始标签body,那么大多数(如果不是所有)浏览器都会在其位置生成一个空段落:

<!DOCTYPE html>
<title></title>
<body>
</p>
</body>

即使结束标记周围存在任何文本,也不会成为该p元素的一部分——它将始终为空,并且文本节点将始终独立存在:

<!DOCTYPE html>
<title></title>
<body>
some text</p>more text
</body>

如果上面的内容body被包裹在<p></p>标签中......我会让你猜会发生什么:

<!DOCTYPE html>
<title></title>
<body>
<p>some text</p>more text</p>
</body>

有趣的是,如果</p>标签前面没有 a <body>or</body>标签,除了 IE9 和更早版本的所有浏览器都不会生成一个空段落(另一方面,IE ≤ 9 将始终创建一个,而 IE10 和更高版本的行为与所有其他浏览器相同) :

<!DOCTYPE html>
<title></title>
</p>
<!DOCTYPE html>
<title></title>
</p><body>
<!DOCTYPE html>
<title></title>
</p></body>

我找不到任何引用规定没有相应开始标记的结束标记应该生成一个空元素,但考虑到它甚至不是有效的 HTML,这不应该让人感到惊讶。确实,我只发现浏览器可以对p元素执行此操作(在某种程度上,br元素也是如此!),但没有任何解释为什么。

在使用传统 HTML 解析器和 HTML5 解析器的浏览器中,它是相当一致的,但是,在 quirks 模式和标准模式下都应用。因此,可以推断这是为了向后兼容早期规范或遗留行为。

事实上,我确实在一个有点相关的问题的答案上找到了这条评论,这基本上证实了这一点:

<p> 标签有效未封闭的原因是,最初 <p> 被定义为“新段落”标记,而不是 p 是容器元素。相当于 <br> 是一个“新行”标记。您可以在 1992 年的这份文件中看到这样的定义:http: //www.w3.org/History/19921103-hypertext/hypertext/WWW/MarkUp/Tags.html和 1993 年的这份文件:http://www.w3。 org/MarkUp/draft-ietf-iiir-html-01.txt因为在更改之前有网页,并且浏览器解析器总是尽可能向后兼容现有的网页内容,所以总是可以使用 <p>那样。

但这并不能完全解释为什么解析器将显式</p>结束标记(带有斜杠)简单地视为......一个标记,并在 DOM 中生成一个空元素。当语法没有像最近 那样严格定义时,这是否是某些解析器错误处理约定的一部分?如果是这样,它是否记录在任何地方?

4

2 回答 2

20

是必需的,记录在 HTML5 中。请参阅http://w3c.github.io/html/syntax.html#the-in-body-insertion-mode并向下搜索An end tag whose tag name is "p"它说:

如果打开元素的堆栈没有按钮范围内的元素与令牌的标签名称相同,那么这是一个解析错误;就好像已经看到了一个带有标签名称“p”的开始标签,然后重新处理当前令牌。

翻译成英文意味着如果标签无法与现有标签匹配,则创建一个p元素。</p><p>

为什么会这样,更难确定。通常,这是因为过去某些浏览器导致这种情况发生为错误,并且网页开始依赖该行为,因此其他浏览器也必须实现它。

于 2012-07-19T23:53:07.640 回答
1

HTML4 DTD声明结束标记对于段落元素是可选的,但开始标记是必需的。

HTML4的SGML 声明声明omittag为“是”,这意味着可以隐含开始标记。

结束标签遵循SGML规则:

结束标签关闭,回到匹配的开始标签,所有未闭合的中间开始标签都省略了结束标签

匿名块框是为文本节点等内联元素生成的,因此它们不需要被段落元素包裹。

Mozilla bug 数据库中有一个线程解释了这种行为:

这是Boris Zbarsky的相关评论:

实际上,据我了解,正确解析 SGML/HTML要求我们这样做。也就是说,下一个标签的“<”是关闭前一个标签的标记的有效方法......

并由Ian Hickson总结:

看来,这里的基本原理是通过延迟任何关闭标记来修复标记,直到所有其他打开的元素都关闭之后,并且不尝试使 DOM 遵循 HTML DTD。

参考

于 2012-08-18T17:17:00.110 回答