css伪类选择器nth-child

关于 css 伪类选择器:nth-child(n)

这几天面试在一个简单的问题上翻车了。

问题大概是这样,问我哪个部分被标红

天真的我回答的是 p 元素 。

答案当然是没有任何元素被标红,原因是 nth-child 会先找到所有父元素下第 n 个子元素,再找其中的 p

也就是它第一步找到的集合是两个 span,其中没有 p 元素。

如果要标红那个 p,须要这么写选择器:

p:nth-of-type(1)

这样是 先选择父元素下的 p,再找到其中的第一个 p

但是

故事到这里并没有完结,我尝试去选择嵌套 p 标签下的 p 标签

令人震惊的是没有任何元素被选中,

尝试了 p > p :nth-child(1)也没有元素被选中p:nth-of-type(1)也不能选择到元素。

只有这样才能成功选择到 p1 。

在这里我已经想到可能是违背了 HTML 标准之类的东西,但 p 是块状元素,不知道为什么不能嵌套另外一个 p 呢?所以去 mozilla 查看一下。看到了

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

其中关于 p 元素的定义

描述是 p 元素表示文本的一个段落,重点是允许的内容是 Phrasing content,再看这个 Phrasing content。

其中不包含 p 标签,所以我认为是 nth-child 选择器 按照 HTML 规范进行了选择上的优化,所以不会在 p 元素下面再去找 p 元素了,吗?

我们再看一下这个结构

在浏览器是怎么渲染的

可以看到,外面包裹的 p,被浏览器渲染成了两个 p 元素。可以猜想到,如果 CSS 写成

1
2
3
p {
color:red
}

span2 也不会被选择中的。

所以最后的总结就是,HTML 代码不规范会使浏览器做出错误的渲染,所以选择器选择出现问题 。