伪类选状态、伪元素造内容:伪类作用于已有元素的状态或位置,不新增dom节点;伪元素在渲染层虚构新节点,用于样式化局部或插入内容,该节点不可查、不可遍历、js不可访问。

伪类是选状态,伪元素是造内容
直接说结论:伪类(:hover、:first-child)作用对象是“已有元素的某种状态或位置”,它不新增任何 DOM 节点;伪元素(::before、::first-letter)则是在渲染层“虚构一个新节点”,用来样式化元素内部某一部分或插入额外内容——这个节点查不到、遍历不到、JS 也拿不到。
:xxx 和 ::xxx 的写法不是风格问题,而是语义分界线
CSS3 明确规定伪类用单冒号 :,伪元素用双冒号 ::。虽然浏览器仍兼容旧写法(比如 :before 能工作),但混用会埋坑:
-
a:hover必须写成单冒号 —— 写成a::hover就完全失效 -
p::first-letter推荐双冒号,写成p:first-letter虽然多数浏览器认,但属于过时语法,且和结构伪类(如:first-child)视觉上难区分 - 现代新增伪元素(如
::placeholder、::backdrop)只支持双冒号写法,单冒号直接忽略
一个元素能叠加多个伪类,但最多只能有两个伪元素
伪类之间可自由组合,比如 button:hover:active:focus 是合法的,表示“同时满足三个状态”;而伪元素受规范限制:
- 每个选择器最多允许一个
::before和一个::after—— 它们算两个独立伪元素,不能写两次::before -
div::before::after是非法语法,浏览器会直接丢弃整个规则 -
span::first-letter::before同样无效 —— 伪元素不能链式叠加,::first-letter已经占用了该元素的伪元素 slot
常见误判场景::first-child vs ::first-letter
这两个名字像,但本质完全不同:
-
li:first-child匹配的是“作为父元素第一个子节点的<li>元素”,它选中的是整个 DOM 元素,不改变内容结构 -
p::first-letter匹配的是“段落文本的第一个字母”,这个字母在 HTML 中并不存在独立标签,CSS 渲染时才临时构造一个抽象盒子来套它 - 更典型的是
input::placeholder—— placeholder 文本由浏览器生成,不在 DOM 中,JS 无法通过element.textContent读取,只能靠伪元素控制样式
真正容易被忽略的点是:伪元素创建的节点不可交互、不可聚焦、不响应事件,也不参与 tab 键导航顺序 —— 它只是视觉层的“贴图”,别指望它替代真实 HTML 结构。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











