应优先用原生html语义化元素替代div:模态框用,折叠面板用,标签页用配,分页用包裹或并设aria-current="page"。

用原生HTML元素替代div做动态容器
很多动态内容可访问性问题,根源在于用 <div> 硬套所有交互逻辑。屏幕阅读器对 <code><div> 没有语义预期,也不会主动播报变化。优先选用带隐式语义的原生标签,能省掉大量 ARIA 补充工作。
<p>常见场景对应关系:</p>
<ul>
<li>模态框 → 用 <code><dialog></dialog>,它自带 aria-modal="true"、焦点陷阱和关闭语义
<details></details> + <summary></summary>,浏览器自动处理 aria-expanded 和键盘(Space/Enter 展开)<div class="tab">,改用 <code><button role="tab"></button> 配合 <div role="tabpanel">(注意:role 是补充,不是替代;<code><button></button> 本身已可聚焦)
<nav></nav> 内,页码用 <ul><li><a></a></li></ul> 或 <button></button>,当前页加 aria-current="page"
用标准属性控制状态与关联,而非手动写ARIA
HTML5 提供了一批内置属性,它们比手写 ARIA 更可靠、更轻量,且部分会自动同步到辅助技术的属性树中。
关键可用属性:
-
hidden:隐藏内容时用它,比display: none或aria-hidden="true"更安全——它同时移除 DOM 可访问性树和视觉渲染 -
disabled:用于<button></button>、<input>等原生控件,会自动触发aria-disabled="true",且阻止键盘聚焦 -
required、minlength、pattern:表单验证属性,屏幕阅读器会读出约束,无需额外aria-invalid(除非需自定义错误文案) -
for+id:<label for="email"></label>关联<input id="email">,比aria-labelledby更直接、更兼容
用 aria-live 区域声明动态更新范围
当内容靠 JS 插入(如搜索结果、通知、表单提交反馈),仅靠 DOM 变化无法被屏幕阅读器感知。必须用 aria-live 显式标记“这里的内容会变,请监听”。
选择策略:
- 重要且需立即播报(如表单成功提示)→
aria-live="polite"或aria-live="assertive"(后者会打断当前播报) - 非关键更新(如实时计数器)→
aria-live="off"+ 手动触发aria-atomic="true"控制播报粒度 - 避免把整个页面或大块区域设为
aria-live,否则容易淹没用户;应精准包裹目标容器,例如:<div aria-live="polite" aria-atomic="true"></div> - 不要依赖
title属性做动态提示——它不触发aria-live,且在多数屏幕阅读器中被忽略或延迟播报
动态内容出现时,焦点必须明确落点
这是最容易被忽略的环节:内容加载完成 ≠ 用户知道该看哪。若新内容无焦点,键盘用户会卡在原位置,屏幕阅读器可能跳过它。
实操要点:
- 模态框打开 → 焦点必须移到
<dialog></dialog>内第一个可聚焦元素(如关闭按钮或主操作按钮),不能留在触发按钮上 - 手风琴展开 → 若内容区含可操作项,焦点应移到该区域起始处(如第一个
<button></button>或<input>);若纯文本,可设tabindex="-1"后.focus() - 列表项新增(如聊天消息)→ 不要自动聚焦新消息(会打断用户当前操作),但需确保其位于 DOM 顺序合理位置,并用
aria-live通知 - 禁用
autofocus属性:它在 Safari 和部分屏幕阅读器中行为不可靠,应由 JS 显式控制焦点时机
aria-expanded 必须和视觉状态严格一致,aria-current 必须随路由或 UI 状态实时更新,任何延迟或错位都会导致辅助技术“说错话”。











