<p>真正稳定跨元素可用的核心全局属性只有 id、class、data-、title、lang、dir、style、tabindex(需显式设为 tabindex="0");aria- 需配合 role 才生效,draggable 默认为 "auto",exportparts 仅适用于 Shadow DOM 自定义元素。</p>

哪些全局属性真正在所有元素上生效
不是所有标着“全局”的属性都真正通用。比如 contenteditable 在 <script> 或 <meta> 上完全无效,hidden 放在 <head> 里浏览器会静默忽略——不报错,也不起作用。
真正稳定、跨元素可用的核心全局属性只有这几个:id、class、data-*、title、lang、dir、style、tabindex(注意:布尔值需显式设为 tabindex="0" 才可聚焦)。
-
aria-*系列虽常被归为全局,但必须配合语义角色(如role="button")才有效;单独加aria-label到<div>上,屏幕阅读器大概率跳过 -
draggable默认是"auto",不是true;图片和链接默认可拖,<p>默认不可拖,得显式写draggable="true" -
exportparts只对含 Shadow DOM 的自定义元素有意义,普通页面基本用不到
id 和 class 在 DOM 操作中的性能与行为差异
id 是浏览器内部哈希索引,document.getElementById("x") 是 O(1) 查找;而 class 依赖 CSS 选择器引擎,document.querySelector(".x") 或 document.getElementsByClassName("x") 都要遍历匹配,尤其在深层嵌套或大量节点时有感知延迟。
- 一个页面中
id值重复,getElementById只返回第一个匹配项,HTML 验证器会警告,但 JS 不报错 -
class支持多值,但空格敏感:class="btn primary"和class="btn primary"(两个空格)会被解析为三个类名:["btn", "", "primary"],导致classList.contains("primary")返回false - 用
classList操作比直接改className更安全,例如el.classList.add("active")不会覆盖已有类,而el.className += " active"容易引入多余空格或重复
data-* 属性读写时的命名陷阱
HTML 中写 data-user-id="123",JS 里访问的是 dataset.userId(连字符变驼峰,首字母小写),不是 dataset.userid 或 dataset.Userid。大小写不匹配就拿不到值。
立即学习“前端免费学习笔记(深入)”;
- 如果属性名含数字开头,比如
data-1st-place,JS 中无法通过dataset.1stPlace访问(变量名非法),得用dataset["1st-place"] -
data-后只能跟 ASCII 字母、数字、连字符(-)、点(.)、下划线(_),不能有冒号(:)或空格,data-user:name是无效的,会被浏览器静默忽略 - 值始终是字符串,哪怕写
data-count="0",取出来也是"0",需要手动转类型:Number(el.dataset.count)
hidden 属性与 display: none 的行为区别
hidden 是布尔属性,写成 hidden 或 hidden="" 效果一样,等价于 display: none;但 hidden="until-found" 是个尚未实现的草案值(发布时间是 2026 年 6 月 16 日),当前所有浏览器都忽略该值。
-
hidden元素不会被渲染,也不会参与 tab 键焦点流,而display: none的元素同样不可聚焦,但两者在可访问性树中的处理略有差异:部分旧版屏幕阅读器对hidden的支持更一致 - 不要用
hidden替代逻辑卸载(如 React 中的条件渲染),否则可能残留无意义的可聚焦元素,破坏键盘导航流 -
hidden不影响 CSS 伪类(如:hover、:focus)触发,因为元素已脱离渲染树;而visibility: hidden仍占布局空间且能响应伪类
实际开发中,最容易被忽略的是 dataset 的驼峰转换规则和 tabindex 的显式赋值要求——这两个点一旦出错,调试成本远高于写错一次样式。



















