为什么<p>标签不能包含<div>标签?

195
据我所知,这是正确的:
<div>
  <p>some words</p>
</div>

但这是错误的:
<p>
  <div>some words</div>
</p>

第一个可以通过W3C验证器(XHTML 1.0),但第二个不能。我知道没有人会写类似第二个的代码,我只是想知道为什么。
其他标签的包含关系呢?

11
因为 <p> 是一个块级元素,用于显示文本,它不允许其他块级元素嵌套在其中,只能使用内联元素如<span><strong> - Bojangles
30
“p”是块级元素与此无关,“div”也是一个块级元素,可以容纳其他块级元素。 - Joey
1
可能是重复的问题:https://dev59.com/YG445IYBdhLWcg3wO31u(未标记):任何好的回答都将回答如何阅读HTML规范,从而也会回答这个问题。 - Ciro Santilli OurBigBook.com
2
将div的样式声明为内联也不起作用。 - Triynko
6个回答

224

查找容纳关系允许的权威来源是HTML规范。例如,请参见http://www.w3.org/TR/html4/sgml/dtd.html。它指定了哪些元素是块级元素,哪些是行内元素。要查找这些列表,请搜索标记为“HTML内容模型”的部分。

对于P元素,规范指定了以下内容,表明P元素只允许包含行内元素。

<!ELEMENT P - O (%inline;)*            -- paragraph -->

这与http://www.w3.org/TR/html401/struct/text.html#h-9.3.1相符,该标准规定P元素“不能包含块级元素(包括P本身)”。


83
我有一个习惯,就是避开规格说明书,这些是我们了解此类事情最权威的文件,因为它们阅读起来很无趣。如果你真正阅读并理解了它们,并用它们来回答问题,那么就加一分吧。 - Stoutie
3
这个是否适用于HTML 5?所提到的规范具体是针对HTML 4的,并且HTML 5没有文档类型定义。 - Ajedi32
2
@Ajedi32 是的,在这里。HTML5 重命名了很多术语,但“允许的内容:短语内容”与上面的 %inline 部分意思相同。还可以参考 Oriol 的回答。 - Mr Lister
1
@Stoutie 没错,这就是为什么 Stack Overflow 存在的原因。 - Captain Hypertext
但是根据这个解释,这与内部有div的div是可以的不一致。 - Ellis

74

简而言之,在DOM中无法将<div>元素放置在<p>元素内,因为开启<div>标签会自动关闭<p>元素。


2
啊,这就解释了在p标签内的div前面有很大的空格,因为实际上p标签是在div之前结束的。 - AaronLS
2
可以在DOM中把一个div元素放在p元素里,例如:myP.appendChild(myDiv)。但HTML解析器不会这样做。 - Oriol
1
不要这样做。你不知道在未来的浏览器中它会如何响应。技术在不断变化。可能会有一个动态HTML解析器,使其无效。Web开发的目标是创建既具有可取性又具有某种兼容性的东西。如果你可以绕过浏览器允许的内容,那么可以肯定的是你不能保证它将永远工作。只需使用span标签...如果需要div,请停止使用p标签。 - user1816910

53
根据HTML5,div元素的内容模型流内容

大多数用于文档和应用程序主体的元素都被归类为流内容。

p元素也属于流内容,只能在期望流内容的地方使用。
因此,div元素可以包含p元素。

然而,p 元素的 内容模型短语内容

短语内容是文档的文本,以及在段落内部标记该文本的元素。一系列 短语内容 形成段落。

这不包括 div 元素,只能在期望流内容的地方使用它们

因此,p元素不能包含div元素。

由于p元素的结束标签可以在紧接着p元素后面出现div元素(等等)时省略,因此以下内容:

<p>
  <div>some words</div>
</p>

被解析为

<p></p>
<div>some words</div>
</p>

而最后的 </p> 是一个错误。

但是如果在CSS中我将div设置为内联,为什么它不遵守呢? - Sanjay
1
由于CSS值是在DOM解析后应用的,即使我们在CSS中将div设置为内联元素也没有用,因为新解析的结构是:
一些单词

``` 我的理解正确吗?
- Sanjay
@Sanjay 是的,看起来你是对的。而且,在我的观察中,如果你把<span>放在<p>里面,然后将span的display设置为“block”,它将呈现为一个典型的块元素,不会产生这样的效果。 - Andrew Naumovich

3
看看这个来自HTML规范的例子: HTML spec
<!-- Example of data from the client database: -->
<!-- Name: Stephane Boyera, Tel: (212) 555-1212, Email: sb@foo.org -->

<DIV id="client-boyera" class="client">
<P><SPAN class="client-title">Client information:</SPAN>
<TABLE class="client-data">
<TR><TH>Last name:<TD>Boyera</TR>
<TR><TH>First name:<TD>Stephane</TR>
<TR><TH>Tel:<TD>(212) 555-1212</TR>
<TR><TH>Email:<TD>sb@foo.org</TR>
</TABLE>
</DIV>

你有注意到什么吗?:在<p>元素中没有结束标签。规范的错误吗?不是

提示1:可选的<p>关闭标签

你可能会问:那么<p>元素如何知道该在哪里停止呢?

根据 w3docs

如果省略了结束标记,则认为段落的结尾与下一个块级元素的开头匹配。

简单来说<div> 是块元素,它的开标签将导致父级 <p> 被关闭,因此 <div> 永远不能嵌套在 <p> 中。

但是反过来呢? 你可能会问

那好...

提示2:需要<div>元素的结束标记

根据 O’Reilly HTML and XHTML Pocket Reference,第四版(第50页)

<div> . . . </div> 开始/结束标记 必须/必须

也就是说,<div>元素的结尾只能通过其关闭标记 </div> 确定,因此其中的 <p> 元素不会中断它。


-1
在XHTML之后,约定已经改变,现在它是XML和HTML公约的混合体,所以第二种方法是错误的,W3C验证器接受符合标准和公约的正确操作。

XHTML 没有太大的变化。p 元素从来没有允许包含 div 元素。 - Quentin

-7
因为 div 标签的优先级高于 p 标签。 p 标签表示段落标签,而 div 标签表示文档标签。
您可以在文档标签中编写多个段落,但不能在段落中编写文档。与 DOC 文件相同。

2
实际上,这是除法。否则它将是<doc> :D - Kyle
6
"Precedence"不是适用于HTML元素的概念,而div表示一个"division",就像@KyleSevenoaks所说的一样 :) - SimplGy
什么是DOC文件?一个Microsoft Word文件? - Peter Mortensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接