content: attr() 只能读取元素的 html 属性(如 data-label),无法读取 css 自定义属性(如 --label);参数须为合法 html 属性名且存在于当前元素,不支持 fallback、类型转换或字符串拼接。

content: attr() 读取的是元素的 HTML 属性,不是 CSS 自定义属性
直接说结论:content: attr(data-label) 只能读取元素上真实存在的 HTML 属性(比如 data-label="编辑"),完全无法读取 style="--label: 编辑" 或 :root { --label: 编辑 } 这类 CSS 自定义属性。这是初学者最容易混淆的一点。
常见错误现象是写了 content: attr(--label) 或 content: attr(style),结果伪元素里啥也没显示——因为浏览器根本不会解析这些,attr() 的参数必须是合法的 HTML 属性名,且该属性需存在于当前元素节点上。
-
attr()的参数不加引号,也不带data-前缀(但属性本身得有);例如元素是<button data-tip="删除"></button>,则写content: attr(data-tip) - 属性值必须是字符串类型;布尔属性(如
disabled)或缺失属性会返回空字符串 - 若属性不存在,
content渲染为空,不会报错也不会 fallback
attr() 不支持 fallback、类型转换或拼接
attr() 是个非常原始的取值机制,没有现代 JS 那种容错能力。它既不能写成 attr(data-label, "默认"),也不能和字符串拼接(比如 "【" attr(data-level) "】" 是非法语法)。
使用场景很受限:适合做简单标签注入,比如图标旁加文字说明、表格行尾加状态标记等轻量级语义增强。
- 合法写法:
content: attr(data-status)(对应<tr data-status="已提交">)<li>非法写法:<code>content: "状态:" attr(data-status)→ 语法错误,整个声明失效 - 非法写法:
content: attr(data-count number)→number/url等 type 参数在绝大多数浏览器中被忽略(仅 CSS Values 4 草案定义,无实际支持) - 避免在 JS 中直接操作
style.setProperty('--label', ...)后指望attr(--label)生效——这条路走不通 - 如果真要结合 CSS 变量,只能靠 JS 把变量值同步写入
data-属性,再由attr()读取 - 注意:
attr()读取的是初始 HTML 属性或 JS 动态设置的属性值,不响应 CSS 类切换带来的属性变化(那是 class 控制的,不是 attr) - 服务端或 JS 注入
data-desc时,需过滤、<code>>、"等字符,否则可能破坏 DOM 结构 - 属性值开头/结尾的空白符会被保留,建议在 JS 设置时用
.trim() - 不要依赖
attr()显示富文本;它只输出纯文本,不解析 HTML 标签
想动态控制 ::before 内容?优先用 data-* + attr(),别硬套 CSS 变量
如果业务逻辑需要频繁变更伪元素内容,正确做法是在 JS 中更新 data- 属性,而不是试图把 CSS 变量“塞进” attr()。
例如按钮文字随语言切换:<button data-i18n-key="save"></button>,配合 JS 根据 locale 查表更新 el.dataset.i18nKey = 'saved',CSS 保持 content: attr(data-i18n-key) 即可响应。
兼容性与特殊字符处理
attr() 在所有现代浏览器中都支持,包括 IE8+,但有个隐蔽坑:如果 HTML 属性值含空格、中文或符号,content 会原样渲染,不会自动转义。遇到 XSS 风险或排版错乱时得提前清洗。
CSS 的 attr() 就是个单向、静态、无逻辑的属性快照工具。它不理解 CSS 变量,不执行表达式,也不做任何转换——你给它什么属性,它就吐什么字符串。用之前先确认那个值是不是真的挂载在 DOM 元素上。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











