全局属性并非所有标签都生效,而是仅在html规范明确定义其运行时行为的上下文中起作用;如id仅用于getelementbyid查找,data-*需通过dataset访问,hidden仅影响渲染,src/required/autoplay等则受限于元素语义类型。

全局属性不是“所有标签都能加”,而是“加了才可能起作用”
很多开发者以为 id、class、data-* 往任意标签上一写就自动生效,其实不然。浏览器只在特定时机、特定上下文中解析这些属性:比如 id 只在 DOM 构建时注册进内部哈希表,供 getElementById 查找;data-* 仅在 JS 调用 element.dataset 时才被解析为驼峰键;hidden 在渲染阶段参与 display 计算,但在 <script></script> 标签上写 hidden 完全无意义——它不控制脚本执行,也不影响 DOM 插入。
关键判断点在于:这个属性是否被 HTML 规范明确定义为“影响该元素的运行时行为”。没定义,就是语法合法但逻辑静默。
局部属性失效 ≠ 写错了,很可能是放错了标签
常见报错如 Invalid value for attribute "src" 或控制台警告 The "href" attribute is not allowed on a "div" element,本质是验证器(或浏览器解析器)发现属性与当前元素语义冲突。例如:
-
src只对<img>、<script></script>、<iframe></iframe>等资源加载型元素有效,写在<div src="xxx"> 上不会报错但也不会触发任何加载行为<li> <code>required只作用于可提交的表单控件(<input>、<select></select>、<textarea></textarea>),加在<span required></span>上既不校验也不阻止提交 -
autoplay在<video></video>上有效,在<audio></audio>上也有效,但在<picture></picture>上完全被忽略——因为<picture></picture>是容器,不直接播放媒体 -
class是给 CSS 和 JS 选择器用的,值必须是空格分隔的纯标识符;含非法字符(如user.role)、未引号包裹的多词(class=btn primary)会截断或解析失败 -
data-*是给 JS 读取结构化数据用的,连字符自动转驼峰(data-user-id→dataset.userId),但数字开头(data-1st-place)或含大写字母(IE11 下data-MyKey→mykey而非myKey)会丢失 - 不要用
data-存状态标记(如data-active="true"),而用class="active";也不要靠class传业务 ID(如class="item-123"),而该用data-id="123" -
tabindex="-1"移除焦点流,但若同时设aria-hidden="true",屏幕阅读器也会跳过——此时元素彻底“双失联”,既不可键盘访问,也不被读屏识别 -
tabindex="0"让元素可聚焦,但若没配role或aria-label,屏幕阅读器可能只朗读“空白按钮”或“可聚焦区域”,用户不知道这是什么 -
aria-labelledby必须指向一个真实存在的id,且该id元素不能有aria-hidden="true",否则引用链断裂,label 不生效
class 和 data-* 的协同陷阱:看似通用,实则边界分明
class 和 data-* 都能写在任何标签上,但它们服务的对象完全不同,混用会导致维护断裂:
aria-* 和 tabindex 的协同失效场景
aria-* 属性和 tabindex 常一起出现,但组合错误会让无障碍完全失效:
真正难的不是写对单个属性,而是理解每个属性在 DOM 解析、样式计算、焦点管理、无障碍树构建这四个阶段中各自参与哪一环。漏掉任一环节,协作就断了。











