伪类选状态,伪元素造内容;:hover等用单冒号因筛选真实元素,::before等用双冒号因生成虚拟盒子;content仅伪元素必需(::before/::after必写,::selection等除外),伪类设content无效。

伪类是“选状态”,伪元素是“造内容”
新手最常卡在:为什么 :hover 用单冒号,::before 却要双冒号?根本不是语法随意,而是语义完全不同——:hover 是在找“正在被悬停的按钮”,它选的是真实存在的 button 元素;而 ::before 是在告诉浏览器:“请在这个按钮前面,凭空生成一个看不见的虚拟盒子,并把 content 塞进去”。这个盒子不在 HTML 里,DOM 中查不到,但能被样式控制。
所以别记“单冒号 vs 双冒号”,先想清楚:你是在筛选已有元素(伪类),还是在注入新内容/装饰部分(伪元素)?
哪些伪类/伪元素必须配 content?哪些根本不能用?
content 属性只对伪元素生效,且是必需的(除 ::first-letter、::first-line 等少数例外)。伪类完全不支持 content,写了也无效。
-
::before和::after必须写content: ""或content: "★",否则不渲染 -
::selection、::placeholder不需要content,它们只是样式化已有文本片段 -
:hover、:focus、:nth-child(2)写content完全没用,浏览器直接忽略
常见错误:a:hover { content: "→"; } —— 这不会在链接上显示箭头,只会让样式失效(或静默丢弃)。
立即学习“前端免费学习笔记(深入)”;
兼容性坑:旧项目里看到 :before 不代表它是伪类
CSS2 时代没有双冒号概念,所有伪元素都用单冒号(如 :before)。CSS3 明确区分后,规定伪元素用 ::,但浏览器为兼容老代码,至今仍支持 :before 写法。所以:
- 看到
:before,别急着归为伪类——它大概率是伪元素,只是用了旧语法 - 新项目一律用
::before、::after,避免混淆;:not()、:is()这类现代伪类永远只能是单冒号 - IE8 及更早只认
:before,但 IE8 已淘汰,除非维护古董系统,否则无需降级
真正要注意的是:像 ::backdrop、::file-selector-button 这类较新的伪元素,只支持双冒号,写成 :backdrop 会直接失效。
一个元素能同时用多个伪类,但伪元素有数量限制
你可以放心叠加伪类:button:hover:active:focus 是合法的,表示“既悬停、又被按下、还聚焦”的瞬间状态。但伪元素不同:
- 一个元素最多允许一个
::before和一个::after(共两个),不能再加第三个 -
div::before::after { ... }是非法语法,浏览器报错或忽略 - 想实现多层装饰?得靠嵌套真实元素,或者用
background-image+mask替代
容易被忽略的点:伪元素默认是 display: inline,且不占文档流(position: absolute 时需注意父容器 position: relative)。这点和伪类选中的真实元素行为完全不同。










