hidden属性使元素彻底退出可访问性树,lang必须设在上才生效,tabindex决定键盘导航与无障碍树纳入关系,title/data-*/spellcheck不进无障碍树。

HTML 全局属性本身不“构建”无障碍树,而是通过触发浏览器解析逻辑、影响 DOM 节点是否进入可访问性树(Accessibility Tree),间接决定屏幕阅读器能否读到它。 真正起作用的是语义化标签 + 合理的全局属性组合,不是单个属性“开关式”控制。
hidden 属性会让节点彻底消失于可访问性树
加了 hidden 的元素,浏览器会同时从渲染树和可访问性树中移除该节点——不是“隐藏”,是“删除”。屏幕阅读器根本不会播报“已隐藏”,也不会感知它的存在。
- 适合场景:临时下线内容、未激活的模态框主体、纯装饰性占位块(且无交互)
- 不适合场景:需要键盘聚焦的折叠菜单项、动态切换的 tab 面板、带 aria-expanded 的树节点
- 常见错误:用
hidden替代aria-hidden="true"控制子节点可见性 → 子节点焦点丢失、JS 无法再操作该 DOM 节点
lang 和 tabindex 直接参与无障碍树初始化阶段
lang 必须写在 标签上,否则整个页面的语音引擎、拼写检查、CSS :lang() 匹配全部失效;tabindex 则决定节点是否被纳入键盘导航流,进而影响其是否被加入可访问性树的“可交互节点列表”。
-
tabindex="0":强制让非交互元素(如<div role="button">)进入可访问性树,并支持 Tab 导航 <li> <code>tabindex="-1":仅支持 JS.focus()聚焦,不进 Tab 流,但仍在可访问性树中(可被 aria-activedescendant 指向) -
tabindex="1"及以上:破坏自然顺序,Lighthouse 直接报错,VoiceOver/NVDA 行为不可预测 - 想让屏幕阅读器播报提示文字?必须用
aria-describedby或aria-label,不能依赖title - 用
data-id存储后端 ID?没问题;但别指望它能提升可访问性 -
spellcheck="false"关闭拼写检查,对视力障碍用户无实际价值,反而可能掩盖输入错误
title、data-*、spellcheck 不进入可访问性树,但影响辅助技术行为
title 仅在鼠标悬停时触发 tooltip,对屏幕阅读器默认不播报(除非用户开启“朗读 title”选项);data-* 完全不参与无障碍树构建,纯 JS 用途;spellcheck 只影响原生输入框的拼写提示,与可访问性树无关。
真正容易被忽略的点是:lang 和 hidden 的生效时机完全不同——前者在 HTML 解析第一帧就锁定语音引擎,后者在 DOM 插入后才触发树重建。JS 动态添加 hidden 是即时的,但动态改 document.documentElement.lang 不会重载已渲染内容的语音行为。











