真正影响运行时行为的全局属性仅有id、class、data-*、tabindex、hidden和contenteditable;其余多数语法合法但无实际效果,如exportparts、dropzone等纯属无效装饰。

真正影响运行时行为的全局属性只有少数几个,其余多数是“语法合法但无实际效果”。别被“所有标签都能加”误导,用错一个,document.getElementById()拿不到元素、dataset读不出值、屏幕阅读器直接跳过——问题往往出在你以为它“应该起作用”的地方。
哪些全局属性真正在 JS 和 CSS 中起作用
HTML 规范定义的 27 个全局属性里,只有以下这些会在开发中高频触发实际行为:
-
id:JS 用document.getElementById()查找(O(1)),CSS 用#header匹配;重复 id 时只返回第一个,不报错但逻辑全崩 -
class:JS 用document.querySelector(".btn")或el.classList.add()操作;空格敏感,class="a b"会被解析为["a", "", "b"] -
data-*:仅在 JS 中通过element.dataset.xxx读写有效;HTML 和 CSS 完全无视它 -
tabindex:值为0或正整数才加入 Tab 焦点流;tabindex="-1"仅支持 JS 聚焦(el.focus()),不参与键盘导航 -
hidden:布尔属性,存在即生效;hidden="false"依然隐藏,浏览器根本不解析值 -
contenteditable:同为布尔属性,只认"true"或"false"字符串;设成"off"或"0"无效
data-* 的命名陷阱和读取边界
看似自由,实则规则严格:
- HTML 写
data-user-id="123",JS 必须用el.dataset.userId(连字符转驼峰,首字母小写),不是el.dataset.userid或el.dataset.UserID - 属性名含数字开头,如
data-1st-place,JS 中不能用点号访问,得写el.dataset["1st-place"] -
data-后只允许 ASCII 字母、数字、连字符(-)、点(.)、下划线(_);data-user:name会被浏览器静默忽略 - 值永远是字符串:
data-count="0"→el.dataset.count === "0",需手动转类型:Number(el.dataset.count)
tabindex 和 contenteditable 的生效前提
这两个属性不是“写了就管用”,有明确的元素类型和状态限制:
-
tabindex只对**默认不可聚焦元素**有意义:<div>、<code><span></span>加tabindex="0"才能进 Tab 流;<button></button>、<a></a>本身可聚焦,加不加都一样 -
contenteditable设为"true"后,内容可编辑,但不会自动触发input或change事件;监听blur更稳妥,部分浏览器才支持input实时捕获 -
contenteditable对<script></script>、<meta>等非渲染元素无效,浏览器直接忽略,也不报错 -
draggable默认是"auto",不是"true";<p></p>默认不可拖,必须显式写draggable="true" -
exportparts:只对含 Shadow DOM 的自定义元素有意义,普通页面加了等于没加 -
dropzone:所有主流浏览器都不支持,2026 年仍处于废弃边缘 -
aria-label单独加在<div> 上可能被跳过——必须配合语义角色,比如 <code>role="button",否则屏幕阅读器不识别 -
title在移动端 Safari 完全不显示,部分屏幕阅读器默认忽略,别当无障碍替代方案 -
lang和dir看似安静,但缺失会影响拼写检查、语音合成、搜索引擎语义识别——它们不显眼,但 SEO 和无障碍依赖它
容易被当成“通用装饰”却实际失效的属性
很多属性写上去没报错,但根本不起作用,纯属心理安慰:
最常翻车的点不在冷门属性,而在 id 重复、class 多余空格、dataset 命名大小写不一致——这些错误不报错,只悄悄让 JS 逻辑失效。调试时优先查这三处,比翻 MDN 更快定位问题。











