content属性仅适用于::before和::after伪元素,用于插入字符串、attr()值或计数器,不支持拼接表达式,无法被选中、复制或被屏幕阅读器识别,且无fallback机制。

content 属性只能用在伪元素上,::before 和 ::after 是唯二合法位置
直接写 content: "x"; 在普通选择器里完全无效,浏览器会静默忽略。CSS 规范强制限定 content 只能用于生成内容的伪元素,不是所有地方都能“插文字”。
- 错误写法:
.box { content: "hello"; }→ 无任何效果,开发者工具里都看不到该声明被应用 - 正确写法必须带伪元素:
.box::before { content: "hello"; } -
::before和::after都是行内级伪元素,不自动换行,也不继承父元素的display,默认就是display: inline
字符串、属性值、计数器——content 支持的三类值不能混用
content 看似简单,但类型系统很严格:字符串字面量("text")、attr() 函数、counter() / counters() 函数,三者语法和行为完全不同,强行拼接会失效。
- 字符串必须加引号:
content: "→";,写成content: →;会被当作无效值丢弃 - 读取 HTML 属性要用
attr(data-label),不是attr("data-label")—— 括号里不能加引号,否则解析失败,返回空字符串 - 计数器必须先用
counter-reset或counter-increment定义过才能用,否则counter(section)渲染为空 - 不能写
content: "第" counter(section) "节";—— CSS 不支持表达式拼接,这种写法整个声明无效
插入图片或图标时,content: url(...) 的路径和加载行为容易被忽略
用 url() 插图看似方便,但路径解析规则和普通 CSS 背景不同:它基于当前 CSS 文件所在位置,不是 HTML 页面位置;且失败时不报错,只留空白。
- 路径必须是相对或绝对 URL,不能是本地文件路径(如
file:///) - 如果 CSS 在
/css/style.css,而图片在/img/icon.svg,就得写content: url(../img/icon.svg); - 图片加载失败(404、CORS、MIME 类型错误)时,伪元素区域彻底空白,连 fallback 文字都没有
- 想兼容降级?只能靠 JS 检测或额外加一层真实 DOM 元素,
content本身不支持fallback机制
伪元素内容无法被选中、复制、屏幕阅读器朗读,这是设计使然,不是 bug
很多人试图让 ::after 里的编号可复制,或希望盲人用户能听到提示文字,结果发现做不到。这不是浏览器实现不到位,而是 CSS 规范明确将伪元素内容定义为“装饰性生成内容”,不属于文档树。
立即学习“前端免费学习笔记(深入)”;
- 用户长按/拖选时,
content生成的文字不会被选中 -
window.getSelection()拿不到这些文本 - 主流屏幕阅读器(NVDA、VoiceOver)默认跳过伪元素内容,除非手动设
aria-hidden: false并配合role="text"(但支持度极差) - 真正需要语义化的内容,比如标题编号、状态标签,应该用真实 HTML 元素 + ARIA,而不是依赖
content
display、visibility、position 影响),以及把 content 当成万能文本注入口,忘了它天生就不属于可访问、可交互、可选中的 DOM 正规军。










