真正能提升无障碍体验的HTML全局属性仅有id、class、lang、dir、title、tabindex、role及aria-、data-;其余所谓全局属性在跨浏览器、跨辅助技术场景下不可靠,易造成假安全感。

真正能提升无障碍体验的 HTML 全局属性,只有 id、class、lang、dir、title、tabindex、role(虽非全局但必须配合)、aria-*(同理)和 data-* —— 其他所谓“全局属性”要么浏览器忽略,要么在关键元素上无效,加了反而制造假安全感。
哪些全局属性真正在所有元素上稳定生效
别被“27个全局属性”的列表带偏。实际跨元素、跨浏览器、跨辅助技术都可靠的,就这几个:
-
id和class:无条件可用,是 DOM 操作和样式控制的基石 -
lang和dir:影响语音合成、断词、排版方向,必须设对,否则 VoiceOver/NVDA 会读错拼音或乱序 -
title:鼠标悬停提示,但对屏幕阅读器支持有限(仅部分触发),不能替代aria-label或真实文本 -
tabindex:只该用0和-1,其他数值(如1)会破坏焦点流,且移动端 Safari 基本无视 -
data-*:纯 JS 数据通道,不参与无障碍,但写错命名(含大写或下划线)会导致dataset读取失败
像 contenteditable 对 <script> 无效,hidden 在 <meta> 里被忽略,draggable 默认是 auto(不是 true),这些都不是“可用”,而是“有条件响应”。
tabindex="0" 和 tabindex="-1" 的真实使用边界
tabindex="0" 不是“让这个 div 可聚焦”就完事,它是交互链的起点,必须配齐三件套:
立即学习“前端免费学习笔记(深入)”;
- 显式声明语义角色:
role="button"、role="tab"、role="checkbox"等,否则屏幕阅读器读作“无名容器” - 监听
keydown:对Enter和Space做响应;Space必须e.preventDefault(),否则触发页面滚动 - 提供视觉焦点反馈:
:focus-visible { outline: 2px solid #007bff; },不能只靠移除outline后留白
tabindex="-1" 不是“隐藏”,是“预留聚焦入口”:
- 模态框打开后,要
.focus()到第一个按钮?那个按钮得提前带tabindex="-1" - 别给整个弹窗
<div class="modal">加tabindex="-1",聚焦后按 Tab 还是跳到页面其他地方 - 异步加载的表单字段,DOM 渲染完成前调
.focus()会静默失败,建议用requestAnimationFrame(() => el.focus())
lang 和 dir 错位带来的硬性断裂
<html lang="zh-CN"> 不是可选项,是解析前提。错位后果直接、不可逆:
-
lang缺失或写成zh:VoiceOver 把“iOS”读成“艾欧斯”,NVDA 对“微信”分词成“微 信”,拼音全错 -
lang写在<body>或<div>上:无效,只有根元素<html>上的才被读屏器识别 -
dir="rtl"用在中文段落里:文字从右往左排,但标点、数字逻辑混乱,输入法光标错位 - 动态切换语言时,只改
i18n.state.lang不碰document.documentElement.lang:辅助技术全程读旧语言,CSS 的:lang(zh-CN)规则也不生效
多语言混排时,局部覆盖用 <p lang="en">,不要指望浏览器自动识别。
aria-* 属性必须和语义结构对齐
ARIA 不是补丁,是契约。单独加 aria-label 到一个没交互的 <div> 上,等于给盲人多念一句废话:
-
aria-label和aria-labelledby不能共存:后者会被完全忽略,Lighthouse 直接报aria-allowed-attr错误 -
aria-labelledby指向的 ID 必须存在且非display: none;visibility: hidden或opacity: 0不影响读取 - 纯装饰性图标(如分割线小图标)才用
alt=""或aria-hidden="true";带状态含义的(红叉/绿勾)必须用aria-label或真实文本说明 - 用
<button>就别写<div role="button">:前者原生支持聚焦、空格/回车、disabled、form关联;后者要手动补全部逻辑,漏一项就卡死键盘用户
最常被忽略的一点:<main> 必须全页唯一且为 <body> 直接子元素,否则 NVDA 会跳过整块主内容——这不是样式问题,是结构树解析失败。



















