<p>不能嵌套<div>

本文最后更新于:1 年前

这是很久以前写网页碰到的事了,当时查到解决方法以后就草草过去了,今天突然想起来觉得还是记一下比较好。

复现一下当时的问题:

我在一个<p>内放了一个<div>标签,代码是这么写的:

1
2
3
4
5
6
<div id="test"> 这是最外面的一个div,套个颜色好区分
<p>
这是一个p标签
<div>这是p标签里面包含的div</div>
</p>
</div>

CSS是这么写的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#test {
height:500px;
width:600px;
background-color:yellow;
}
#test p{
height:100px;
width:150px;
background-color:red;
}
#test p div{
height:50px;
width:80px;
background-color:blue;
}

然后当我在浏览器里打开这个网页的时候,发现显示出来是这个样的:

嗯?好像哪不对?里面的div不应该是蓝色的吗,赶紧到控制台查看元素,发现更不对了:

为什么div跑到p外面了,为什么div下面还有个空的p?吓得我赶紧在里面又放了个<span>试试,一试好像没什么问题,但是div的位置依旧不对劲,这是怎么肥四??我记得p和div都是块级标签,应该是可以互相嵌套的啊,想了半天没想通之后我去查了些资料,终于搞明白原来有的块元素不能包含另一些块元素。

而且根据新的HTML规范,元素类型已经不按inline和block来区分了,

规范中的每个元素都有以下两项:

  • Categories
  • Content Model

Categories 是该元素本身的分类,content model 规定了合法的元素的内容(子元素、文本等)类型。

MDN中的介绍是这样的:

每一个HTML元素都必须遵循定义了它可以包含哪一类内容的规则。 这些规则被归类为几个常见的元素内容模型(content model)。每个HTML元素都属于0个、1 个或多个内容模型,每个模型都有一些规则使得元素中的内容必须遵循一个HTML规范文档( HTML-conformant document)。

以下是三种类型的内容分类:

  • 主内容类,描述了很多元素共享的内容规范;
  • 表单相关的内容类,描述了表单相关元素共有的内容规范;
  • 特殊内容类,描述了仅仅在某些特殊元素上才需要遵守的内容规范,通常这些元素都有特殊的上下文关系。

每个元素都有内容分类(Content categories)和允许的内容(Permitted content)两项来说明元素属于何种内容模型和该元素内允许的内容类型。

回到原来的问题上来,p标签不能包含div的原因其实就是因为新规范中规定了p元素允许的内容不包括div,所以才会出现上面的问题,同样不能包含的还有其他元素,比如<p>自己,<ul>列表等都不能被放进p标签内。

规范其实也说明了一点,虽然有时候在HTML中随意嵌套元素也可以正常显示,但事实上元素应该在他出现的地方才能更好的发挥作用,比如:<ul><ol><dl><table>,它们的子一层都是指定的元素,<ul>、<ol>的子一级是<li><dl>的子一级必须是<dt>或者<dd><table>的子一层可以是<caption><thead><tfoot><tbody>等,而再子一层是<tr> <tr>只存在于<thead><tfoot><tbody>中),之后才是<td>或者<th>。以后我们写完代码可以去W3C验证平台上检查一下自己的代码存在什么问题,就能减少一些像上面这样的错误。

参考链接

a 标签为什么能够包含块级元素? - 顾轶灵的回答 - 知乎

HTML中为何p标签内不可包含div标签?那哪些块元素里面不能放哪些块元素呢?

HTML Standard

<p> - HTML(超文本标记语言) | MDN

内容分类 - Web 开发者指南 | MDN