思维模型

无障碍模态对话框

将键盘焦点限制在内部、向屏幕阅读器正确传达自身信息,并让所有用户都能完成任务而不会被困在弹出层中的模态对话框。

探索一下

构建模态对话框时,无障碍处理步骤的顺序很关键。漏掉一步,使用键盘和屏幕阅读器的用户就可能被困住,或无法使用你的界面。

打开无障碍模态对话框时,第一步是什么?

你将学会构建真正无障碍的模态对话框所需的完整步骤。

理解概念

理解概念

无障碍模态对话框是一种弹出窗口,会将键盘焦点限制在窗口内部,避免你误操作后面的页面。打开模态对话框时,焦点会自动移入其中;用 Tab 键导航时,焦点会留在对话框内;关闭后,焦点会回到你之前点击的按钮上。这样,使用键盘和屏幕阅读器的用户就能顺利完成任务,不会迷失位置或被困住。例如,点击“删除账户”后出现确认对话框,无障碍实现会把键盘焦点移入对话框,让你用 Tab 键在“取消”和“确认”按钮之间切换,并在操作结束后回到原来的位置。 试试这样:打开你网站上的任意一个模态对话框,只用 Tab 键导航,看看能否在不离开对话框的情况下到达每个按钮?

详细讲解

详细讲解

无障碍模态对话框需要按顺序管理焦点,并配合使用无障碍属性。首先,对话框打开时,JavaScript 会将键盘焦点移到内部的某个元素上,通常是第一个交互元素;如果对话框内容较多,也可以是标题,或最常用的按钮。这会告诉辅助技术,当前操作区域已切换到对话框。随后,焦点会被限制在内部:按 Tab 和 Shift+Tab 时,只会在对话框内的交互元素之间循环,不会移到背景页面。

模态对话框本身需要特定的 ARIA 属性:使用 role="dialog"(或原生的 <dialog> 元素),让 aria-labelledby 指向对话框标题,并设置 aria-modal="true",告诉屏幕阅读器,对话框外的内容暂时不可用。这些属性与 JavaScript 实现的焦点限制相互配合,为辅助技术用户提供完整的使用体验。例如,Cookie 同意对话框将焦点限制在内部,可以确保键盘用户先作出回应,再浏览网站的其他部分,同时也让屏幕阅读器用户知道背景页面暂时无法交互。

关闭对话框时,这个过程会反向进行:焦点回到触发它的元素,或另一个合理的位置,帮助你保持在文档中的位置。无论何时,按 Escape 键都必须能关闭对话框,为用户提供标准的退出方式。这套完整流程适用于各种场景:电商网站的结账确认对话框、效率应用的设置面板,以及银行应用的安全验证对话框,都依赖这一模式,让用户无论采用哪种导航方式,都能完成关键任务。

遇到嵌套对话框、动态内容或移动端场景时,实现会更加复杂。例如,一个模态对话框又打开另一个模态对话框,比如从配送选项对话框中打开地址表单,每一层都必须维护自己的焦点范围,同时正确管理各层的堆叠关系。移动端屏幕阅读器还会带来额外挑战,因为它们可能使用不同的触摸手势来导航。使用真实的辅助技术进行测试仍然必不可少,因为遵循规范并不能保证不同浏览器与屏幕阅读器组合的行为一致。

研究依据

研究依据

无障碍模态对话框是网页无障碍领域中已有充分文档说明的设计模式,正式规范也明确了它应有的行为。《WAI-ARIA 编写实践指南》(APG)为模态对话框的实现提供了权威规范,规定了键盘交互、焦点管理以及必需的 ARIA 属性,其中包括 aria-modal="true",用于告知辅助技术,背景内容处于不可交互状态 [1]。HTML 的 <dialog> 元素提供原生模态支持,并内置焦点限制功能,但在生产环境中使用时,需要仔细考虑浏览器兼容性差异 [2]。

  • W3C《WCAG 2.1》的成功准则 2.4.3(焦点顺序)要求键盘导航遵循合理的顺序。对于模态对话框,这意味着将焦点保持在对话框内,并在关闭时将焦点返回到适当位置 [1]。
  • 无障碍咨询公司 TPGi 的研究记录了不同屏幕阅读器对 aria-modal 属性的支持差异,Safari 与 VoiceOver 的组合尤其如此,因此需要补充措施,例如在背景内容上配合使用 inert 属性和 aria-hidden [3]。
  • APG 根据对话框内容类型规定了初始焦点的放置策略:简单对话框应聚焦第一个交互元素;需要按结构阅读的内容应聚焦静态文本元素;涉及不可逆后果的确认对话框应聚焦破坏性最小的操作 [1]。
  • 不同浏览器对原生 <dialog> 元素的支持仍不一致,Safari 和较旧的浏览器缺乏完整支持,因此生产环境需要提供基于 ARIA 的后备实现 [2]。

处理规范与辅助技术实际行为之间的差异,会增加实现的复杂度。例如,理论上 aria-modal="true" 应阻止屏幕阅读器的虚拟光标访问背景内容,但实际测试发现,支持仍有缺口,尤其是 iOS 和 macOS 上的 VoiceOver。规范与实现之间的这种差距,使得开发者需要采用多层防护策略,将 ARIA 属性、JavaScript 焦点限制和 HTML 的 inert 属性结合起来使用。

适用局限

适用局限

模态对话框模式存在一些已有充分记录的局限和实现难点。不同屏幕阅读器对 aria-modal 的支持差异很大:Safari 上的 VoiceOver 存在已知问题,使用 aria-modal 可能导致静态内容无法访问;某些浏览器与屏幕阅读器的组合也无法正确处理 aria-modal="false"。原生 <dialog> 元素缺乏一致的浏览器支持,尤其是在 Safari 和较旧的浏览器中,因此需要使用兼容补丁(polyfill)或基于 ARIA 的替代方案。移动端无障碍又增加了一层复杂性,因为触摸手势和移动端屏幕阅读器与焦点管理的交互方式,不同于桌面端的键盘导航。多个对话框层层堆叠,也就是嵌套模态对话框,会进一步放大这些问题,需要仔细管理多个焦点范围和 z-index 层级。有些实现过度依赖 JavaScript,没有考虑渐进增强,导致脚本失效时用户无法无障碍地使用界面。最后,模态对话框本身在用户体验设计中仍有争议:研究表明,它们会打断用户的操作流程,也可能让用户迷失方向。因此,当非模态方案足以满足需求时,最有利于无障碍使用的做法往往是完全避免使用模态对话框。

参考来源

参考来源

试一试

检验你的理解

一位开发者创建了一个模态对话框,用户点击“设置”按钮就会打开它。对话框已设置正确的 ARIA 属性,但打开后,键盘焦点仍停留在背景中的“设置”按钮上。用户按 Tab 键时,焦点会移到主页面的下一个元素,而不是进入对话框。这里缺少了哪项关键的无障碍步骤?

查看文章解释

答案: 在模态对话框打开时,将键盘焦点移入其中

这里缺少关键的第一步:对话框打开时,通过代码将焦点移入其中。虽然 `role='dialog'` 和 `aria-modal='true'` 等 ARIA 属性能帮助屏幕阅读器理解当前操作区域,但它们不会自动移动键盘焦点。JavaScript 必须主动将焦点设置到对话框内的某个元素上(`document.activeElement = modalElement` 或使用 `.focus()` 方法)。否则,键盘用户的焦点仍停留在触发元素上,按 Tab 键就可能完全绕过对话框,违反将焦点限制在模态对话框内的原则。这也说明了为什么 APG 将移动焦点规定为模态对话框打开时的第一个必需操作。

你正在实现一个模态对话框,其中显示一份很长的隐私政策,底部只有一个“接受”按钮。初始焦点应该放在哪里?

查看文章解释

答案: 模态对话框的标题上

对于内容较多、首个交互元素位于底部的对话框,这个元素可能已在可视区域之外,APG 建议通过 `tabindex='-1'`,将初始焦点设置在对话框标题等静态元素上。这样,屏幕阅读器用户就能先听取并浏览标题、段落等语义结构,再到达交互按钮。如果直接将焦点放在底部的“接受”按钮上,用户可能会错过上方的重要政策内容。这说明,初始焦点的位置必须根据对话框的内容结构调整,而不是始终默认放在第一个交互元素上。

判断对错:仅使用 aria-modal='true' 属性,就足以将键盘焦点限制在模态对话框内。

查看文章解释

答案: 错

错。`aria-modal` 属性会告诉辅助技术,背景内容处于不可交互状态,但它本身并不会限制键盘焦点。要将键盘焦点限制在内部,需要通过 JavaScript 实现:监听 Tab 和 Shift+Tab 的 keydown 事件,检测焦点何时将要离开对话框,再通过代码将焦点循环移回对话框内第一个或最后一个可聚焦元素。`aria-modal` 能帮助屏幕阅读器理解当前处于模态对话框中,但不能阻止键盘用户用 Tab 键移出对话框。因此,无障碍模态对话框需要同时使用 ARIA 属性和 JavaScript 焦点管理,才能提供完整的键盘无障碍支持。

继续探索

为眼前的选择,再找一个有用的想法。

Reframo 的全部已发布文章均可免费阅读。准备好后,随时继续探索。