必须用双冒号的伪元素包括::placeholder、::selection、::backdrop、::marker、::backdrop等css3新增伪元素;:before、:after、:first-letter、:first-line属过渡期,推荐但非强制改双冒号。

哪些伪元素必须改双冒号
不是所有单冒号伪元素都得改,但新增的伪元素(::placeholder、::selection、::backdrop)在 Chrome 57+、Firefox 51+、Safari 10.1+ 中只认双冒号写法。单冒号如 :placeholder 会被浏览器直接忽略——DevTools 样式面板里根本看不到这条规则,也不报错。
已存在的 :before 和 :after 属于“过渡期伪元素”,双冒号是标准,单冒号仅因兼容保留。但它们不是“可选”,而是“应统一”:一旦项目用了 PostCSS、cssnano 或 Stylelint,单冒号可能被压缩丢弃或报 selector-no-vendor-prefix 类警告(实际是解析器判定为非法选择器)。
-
::before/::after→ 必须改为双冒号(尤其当与伪类混用时) -
::first-letter/::first-line→ 推荐双冒号,旧版 IE8 不支持,但现代项目通常已不兼容 IE8 -
::marker→ CSS3 新增,仅支持双冒号
:not() 里混用单/双冒号会静默失效
迁移时最容易踩坑的是 :not() 内部。它只接受单冒号伪类,且不允许出现任何伪元素。写成 :not(::before) 或 :not(:hover::before),整条规则都会被浏览器跳过——控制台无提示,样式不生效,连 DevTools 的 computed 面板都找不到它。
常见错误场景:
-
a:not(::visited)→::visited语法非法,:not()内必须用:visited -
div:not(.active:hover)→ 复合选择器不被:not()支持,应拆成div:not(.active):not(:hover) -
button:hover::before合法,但写成button::before:hover就完全无效——伪元素没有自己的:hover状态
伪类 + 伪元素组合顺序不能颠倒
迁移后若发现某些悬停效果突然消失,先检查组合顺序。正确写法是 button:hover::before,表示「按钮处于 hover 状态时,其 ::before 伪元素应用样式」;反过来 button::before:hover 是非法的,因为 ::before 不是真实 DOM 节点,无法触发交互事件。
这个顺序不是风格约定,而是渲染引擎的硬性限制。即使你加了 !important,浏览器也会整条规则忽略。
- 合法:
p:focus::selection、input:disabled::placeholder - 非法:
p::selection:focus、input::placeholder:disabled - 注意:
:focus-visible是伪类,永远用单冒号;::placeholder是伪元素,永远用双冒号
构建工具和团队协作中的隐性风险
语法改完不等于问题解决。PostCSS 插件(如 postcss-preset-env)可能把单冒号规则当作过时语法自动转换或丢弃;cssnano 在压缩阶段可能合并重复规则时误判 :before 和 ::before 为不同选择器,导致样式丢失。
更隐蔽的是层叠上下文影响:一旦宿主元素设了 position: relative 和 z-index,它的 ::before 就自动成为第一个子 stacking context。此时伪元素和宿主内部其他子元素的层级关系,必须靠显式的 z-index 控制——这不是语法迁移能解决的,但常被归咎于“改冒号后样式乱了”。
真正容易被忽略的,是这种渲染模型层面的约束:它不报错、不警告,只在特定布局下才暴露,且很难和 CSS 语法错误区分开。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











