data-属性CSS选择器严格匹配HTML原始写法,JS中dataset自动驼峰转换,但CSS不转换;动态插入需先设属性再挂载;纯CSS无法跨元素联动,须JS配合class控制;data-无响应性,需验证属性是否存在。

直接用 [data-foo] 或 [data-foo="bar"] 就能生效,但样式“不更新”或“不匹配”基本都是拼写、作用域或时机问题,不是 CSS 不支持。
data-* 属性名和 dataset 键名大小写转换规则必须对齐
HTML 中写 data-user-id="123",JS 里必须用 el.dataset.userId 读写;写成 el.dataset.userid 或 el.dataset.UserID 都拿不到值。CSS 选择器则严格按 HTML 中的原始写法匹配:[data-user-id="123"] 有效,[data-userId="123"] 或 [data-UserId="123"] 全无效。
- 驼峰转换只发生在 JS 的
dataset访问时,CSS 从不转换 -
data-status-code→ JS 是dataset.statusCode,CSS 是[data-status-code] - 所有
data-属性值默认小写,避免混用Dark和dark
动态插入元素前必须显式设置 data-* 属性
用 innerHTML 或 createElement 插入新节点后才发现没样式?大概率是没同步设 data- 值。CSS 不会“等待”属性补上,它只在元素挂载时做一次快照匹配。
- 错误写法:
el.innerHTML = '<div class="item">text</div>'→ 没data-,[data-type="card"]规则完全不触发 - 正确写法:先创建元素,再设属性:
const div = document.createElement('div'); div.dataset.type = 'card'; div.textContent = 'text'; parent.append(div); - 若用模板字符串,务必写全:
el.innerHTML = '<div data-type="card" class="item">text</div>'
想让多个元素联动响应同一 data-* 值?纯 CSS 做不了,得靠 JS
CSS 的 :hover 或属性选择器只能影响当前元素及其后代,无法跨兄弟、跨父级“广播”状态。比如表格中 hover 一列,想高亮所有同 data-index="2" 的单元格,必须用 JS 查找并批量操作。
立即学习“前端免费学习笔记(深入)”;
- 监听事件:
table.addEventListener('mouseover', e => { if (e.target.matches('td')) { const idx = e.target.dataset.index; } - 批量选中:
document.querySelectorAll(`td[data-index="${idx}"]`) - 加类而非改
dataset:给这批元素统一加col-hover类,样式写在.col-hover上更稳定 - 避免反复 setAttribute:批量样式切换优先用 class 切换,比循环改
dataset性能好、逻辑清
data-* 不能直接驱动 CSS 变量或过渡动画
attr(data-color) 在 content 以外的属性里不被支持,也**不会触发重绘**。想用 data- 控制主题色,必须配合 :root + 选择器层级覆盖。
- 正确结构:
:root { --bg: #fff; } [data-theme="dark"] :root { --bg: #121212; },然后在元素上写background-color: var(--bg); - 过渡要加在使用
var()的属性上,比如transition: background-color 0.2s;,不是加在[data-theme]上 - 切换时只调
document.documentElement.setAttribute('data-theme', 'dark'),别碰style.setProperty - Shadow DOM 内部需额外声明
:host([data-theme="dark"]) :root才能穿透
真正容易被忽略的是:data-* 本身没有“响应性”,它只是个静态标记。样式是否生效,取决于你写的选择器是否够精确、JS 是否在正确时机写入属性、以及浏览器是否真把那个元素纳入了样式计算范围——别怪 CSS,先查 el.hasAttribute('data-xxx')。


















