用[data-*]属性选择器替代class可避免样式污染、命名冲突,提升语义化和作用域隔离;配合:is()和attr()能简化多状态控制与动态内容输出,但高频切换场景仍宜用class。
[data-*] 属性选择器替代 class 做状态区分纯 CSS class 容易泛化,比如 .active 可能被多个组件复用,导致样式污染。用自定义属性(data-)绑定具体上下文,能天然隔离作用域。
例如按钮在表单提交中处于「禁用且带校验错误」状态,可写:
对应 CSS:[data-state="error"][data-disabled="true"] { opacity: 0.4; cursor: not-allowed; }
[data-*] 选择器.btn--error-disabled 那样依赖 BEM 约定,data- 属性名由你完全控制el.dataset.state = 'success' 比 el.classList.replace('error', 'success') 更直白:is() + [data-*] 组合简化多状态选择器当一个组件有 3 种以上状态(如 idle / loading / success / error),为每种写独立规则会冗余。用 :is() 把它们聚合成一组,再配合 [data-status] 统一控制基础样式。
示例:
[data-status]:is([data-status="loading"], [data-status="error"]) { transition: none; }
[data-status="success"] { color: #28a745; }
[data-status="error"] { color: #dc3545; }
:is() 支持逗号分隔的多个选择器,且不提升整体优先级,比用 !important 或追加 class 更安全:is();旧版本需降级为重复书写或 JS 注入 class:is(:is(...)),部分浏览器解析异常,直接扁平写attr() 在伪元素中动态输出 data- 值想让 tooltip 文字随 data-hint 变化,又不想用 JS 插入 DOM?attr() 能直接把属性值透传进 ::before / ::after 的 content。
示例:
?[data-hint]::after { content: attr(data-hint); display: none; }
[data-hint]:hover::after { display: inline; }
at
tr() 只读取字符串值,不能做计算或 fallback(如 attr(data-x, "default") 不合法)data-hint="用户未登录 → 请先授权"),CSS 里必须用双引号包裹 content
content 属性中使用,比如 width: attr(data-width px) 是无效的[data-*] 替代 class 处理高频样式切换如果某个属性(如 data-theme="dark")需要在全站频繁切换,靠 JS 批量修改 dataset 会触发大量重排重绘;此时不如用根级 class 控制,再用 :root 或 html 选择器承接。
document.documentElement.classList.toggle('dark'),而不是遍历所有元素设 data-theme
[data-*] 适合低频、局部、语义强的状态(如表单字段校验结果、卡片加载阶段),不适合全局主题或动画帧级更新data- 属性比 class 更显眼,但批量查找仍不如 class 名直观——建议保留有意义的 class 作结构标识,data- 仅承载动态元信息