为什么:first-child属于伪选择器,而:first-line属于伪元素?
为什么
:first-child是伪类,而:first-line属于伪元素 核心区别根本不是「是不是动态」,而是两者匹配的目标从根上就不一样,你觉得两者都存在于DOM里,是把浏览器渲染出的视觉结果和DOM树的真实节点搞混了。
伪类(比如:first-child)的本质:筛选已有的真实DOM元素
伪类本质上是给选择器加了一层状态/位置的筛选条件,它最终匹配到的永远是一个完整的、真实存在于DOM树里的元素:
- 比如
div p:first-child,选中的是「作为父元素第一个子节点」的那个<p>标签本身,这个<p>是你写在HTML源码里、能通过JS直接获取到的真实节点,:first-child只是给所有div p加了个“必须是第一个子元素”的筛选规则而已,没有创造任何新的节点。 - 同类的
:hover、:checked、:disabled、:nth-of-type()逻辑完全一致:都是给已有的真实DOM元素附加匹配条件,不会凭空生成DOM里不存在的东西。
伪元素(比如::first-line)的本质:选中/创建DOM里不存在的虚拟片段
伪元素的作用是定位到真实元素内部、一个不存在于DOM树的虚拟子部分,甚至可以凭空生成虚拟内容,你在HTML源码里根本找不到和它对应的标签:
- 拿
::first-line(早期规范允许单冒号写法:first-line,CSS3之后推荐用双冒号和伪类做明确区分)来说,它匹配的是块级元素渲染时的「第一行文本」——这个范围根本不是固定的:你拖动浏览器窗口改宽度、调整字体大小、修改行高,第一行包含的文字内容会随时变化,你不可能在HTML里提前用标签把“第一行”包起来,DOM里也从来没有过承载第一行内容的独立节点,这个范围完全是浏览器渲染阶段动态计算出来的虚拟区域。 - 你可以给这个虚拟区域单独设置字体、颜色样式,但永远没法通过JS直接拿到所谓的“第一行节点”,因为它从始至终就没在DOM里存在过。同类的
::before、::after、::first-letter、::selection全是这个逻辑:操作的都是真实DOM之外的虚拟渲染单元。
给你个最简单的判断方法:如果把选择器里的这个关键字删掉,剩下的部分还能选中一个真实存在的DOM元素,那它就是伪类;如果删掉之后,你根本找不到那个被应用样式的对应节点,那它就是伪元素。
内容的提问来源于stack exchange,提问作者user14624278
相关产品推荐
相关产品推荐

