伪类选状态、伪元素造内容;单冒号用于伪类(如:hover),双冒号强制用于伪元素(如::before),css3以此明确语义区分,旧写法因兼容保留但不推荐。

伪类和伪元素本质是两类不同机制:一个选状态,一个造内容;单冒号是历史兼容写法,双冒号才是 CSS3 明确规定的语义分隔符。
伪类用单冒号 :hover 是因为它的本职是“加条件筛选”
伪类不生成新节点,只对已有 DOM 元素施加样式条件。比如 a:hover 选中的仍是那个 <a></a> 标签,只是在鼠标悬停时激活样式。它和 .btn.active 的逻辑一致——都是“给某个元素加状态标识”。CSS2 就用单冒号定义了所有伪类,后来也没必要改,所以至今 :focus、:nth-child() 等仍合法使用单冒号。
- 所有主流浏览器都支持单冒号伪类,无需考虑降级
- 不能把伪类写成双冒号(如
::hover),部分浏览器会直接忽略 -
:not()里嵌套伪类必须用单冒号,例如:not(:hover)
伪元素强制推荐双冒号 ::before 是为了和伪类划清语义边界
CSS3 规范明确要求伪元素必须用双冒号,目的是强调它和伪类的底层差异:::before 插入的内容不在 DOM 中,无法被 document.querySelector 获取,也不参与事件流。双冒号就是个视觉提示:“这里不是在选元素,是在造东西”。虽然浏览器仍支持 :before 这种旧写法(向后兼容),但现代项目应统一用 ::before。
-
::first-letter和::first-line必须用双冒号,单冒号在某些浏览器中可能失效 -
::placeholder在 Chrome/Firefox 中仅认双冒号写法 - 若同时用
::before和::after,它们共用同一个 stacking context,顺序由 CSS 声明先后决定
为什么 :before 这种单冒号写法还没被废弃?
因为 CSS2.1 定义了 :before 和 :after 为伪类,后来 CSS3 才把它们“升格”为伪元素并引入双冒号语法。为避免大量老代码崩溃,浏览器选择长期保留单冒号兼容模式。但这不意味着它是正确实践:
- IE8 及更早版本只认单冒号,但已无实际兼容价值
- ESLint 或 Stylelint 配置
css/selector-no-vendor-prefix类规则时,会把:before当作过时写法报错 - 当伪元素和伪类混用(如
button:hover::before),必须确保伪类在前、伪元素在后,顺序颠倒会导致整个规则无效
真正容易被忽略的是层叠上下文问题:伪元素默认插入在宿主元素的内容层之上,但若宿主设置了 z-index 且为定位元素,::before 会成为其第一个子层叠上下文,此时它和宿主内其他子元素的层级关系需额外计算——这不是语法问题,而是渲染模型里的隐性约束。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











