伪元素必须用双冒号::,伪类用单冒号:;::before/::after是唯一允许共存的两个伪元素,::selection等无需content且必须双冒号,渲染时机晚于伪类。

伪类用单冒号 :hover,伪元素必须用双冒号 ::before
语法不是历史包袱,而是规范意图的直接体现。CSS3 明确规定:所有伪元素必须使用 ::(如 ::before、::first-letter),单冒号 :before 仅作为向后兼容存在;而伪类始终用单冒号 :(如 :hover、:nth-child())。浏览器虽仍支持 :before,但新伪元素(如 ::highlight、::backdrop)只认双冒号——写成 :highlight 会直接失效。
常见踩坑点:
- 在 Vue / React 的 scoped CSS 或 Shadow DOM 中,
:before可能被预处理器错误解析或作用域隔离截断,强制用::before更稳妥 - PostCSS 插件(如 autoprefixer)默认不处理单冒号伪元素,需额外配置或手动替换
-
:not()里不能嵌套伪元素(如:not(::before)是非法语法),但可以嵌套伪类(:not(:disabled)合法)
:hover 选的是元素本身的状态,::before 插的是虚拟 DOM 节点
这是根本差异所在::hover 不新增任何节点,只是给当前元素临时加一组样式规则;而 ::before 会在渲染树中生成一个**独立的、可继承样式、可参与盒模型计算**的虚拟节点(虽然它不出现在 DevTools 的 Elements 面板原始 HTML 中)。
这意味着:
-
::before可以设置content、display、width、z-index,甚至触发伪元素自身的:hover(需配合pointer-events: auto) -
:focus无法作用于::before,因为它不是可聚焦元素;但你可以用input:focus::before给输入框添加聚焦装饰 - 伪元素受父元素
overflow: hidden影响,但伪类不会——div:hover改背景色,不影响溢出裁剪逻辑
一个元素能叠加多个伪类,但最多只能有两个伪元素
CSS 规范限制每个选择器只能声明一个伪元素,但 ::before 和 ::after 被视为两个独立的“槽位”,所以一个元素最多允许这两个共存。超出(比如再写 ::first-line)会被忽略。
而伪类完全无此限制:button:hover:active:focus 是合法且常见的链式状态表达。
实际开发中要注意:
-
div::before::after是无效写法,必须分开写成div::before和div::after -
img::before默认不生效——<img>是替换元素,::before/::after在其上无渲染位置,除非设display: block或inline-block -
input[type="text"]::before同样无效,表单控件的渲染由 UA 样式控制,伪元素无法插入内容
::selection 这类伪元素不依赖 content,但必须用双冒号
很多人以为伪元素都得配 content 才能显示,其实像 ::selection、::placeholder、::spelling-error 这些是作用于元素**已有内容的特定片段**,它们不插入新节点,而是对渲染层做局部样式覆盖。
关键点:
-
::selection必须用双冒号,:selection在部分新版浏览器(如 Chrome 128+)已弃用并警告 -
content属性对::selection无效,设了也无效果;但color、background、text-shadow等可生效 -
::placeholder在<input>上有效,但在<textarea></textarea>上需注意 Safari 对::-webkit-input-placeholder的旧前缀依赖
div:hover::before 中,:hover 状态一触发,::before 才开始创建并绘制——这意味着它的动画起始帧可能有微小延迟,复杂交互动画中要预留这个间隙。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











