角色 窗口
dialog
将容器标记为模态或非模态对话框。建议使用原生 <dialog> 元素配合 showModal()——它可自动处理焦点限制、顶层渲染、背景遮罩以及 Escape 关闭功能。仅在无法使用原生元素时才借助 role="dialog"。
适用场景
使用通过 .showModal() 打开的 <dialog> 元素。该原生元素在所有主流浏览器中均受支持,可自动处理背景失活、焦点限制、Escape 关闭、::backdrop 样式钩子以及顶层渲染,省去约 200 行脆弱的 JavaScript 代码。
仅在以下情况下才在 <div> 上使用 role="dialog":
- 需要支持 Chrome 37 / Firefox 98 / Safari 15.4 之前的旧版浏览器(2026 年几乎不会出现此情况)。
- 设计要求对话框不能位于顶层(极为罕见)。
- 在重构过程中修补不可访问的自定义模态组件。
每个对话框都必须具有可访问名称(将 aria-labelledby 指向可见标题是最佳做法)。模态对话框还需要设置 aria-modal="true"。
键盘与焦点契约
依据 APG 对话框(模态)模式:
- 打开时,焦点移至对话框内的第一个可聚焦元素(通常是关闭按钮或主要输入框)。
- Tab 和 Shift+Tab 在对话框内部循环移动焦点——即”焦点限制”。从最后一个元素按 Tab 返回第一个;从第一个元素按 Shift+Tab 返回最后一个。
- 按 Escape 关闭对话框。
- 关闭后,焦点返回至触发对话框的元素。保存并恢复焦点是不可或缺的;失去位置的用户将无从定位。
- 对话框打开期间,其余页面内容须设为
inert(或作为备用方案设置aria-hidden="true"且不可聚焦)。
常见错误
- 自定义对话框缺少焦点限制。按 Tab 后焦点跳出对话框,用户丢失上下文。
- 关闭时未将焦点还原至触发元素。下一次按 Tab 落在文档主体上。
- 尽管背景内容在视觉上被对话框遮挡,仍可通过 Tab 键聚焦到背景元素。
- 缺少可访问名称。对话框打开后,屏幕阅读器仅播报”对话框”。
- 自定义对话框未设置
aria-modal="true"——辅助技术将其视为内联内容。 - Escape 关闭对话框时,若对话框通过 portal 渲染,关闭动画期间键盘焦点可能丢失。
示例
<!-- 推荐用法 -->
<dialog id="confirm">
<h2>Delete this draft?</h2>
<p>This cannot be undone.</p>
<form method="dialog">
<button value="cancel">Cancel</button>
<button value="delete" autofocus>Delete</button>
</form>
</dialog>
<script>
document.getElementById('confirm').showModal();
</script>
<!-- 当无法使用 <dialog> 时 -->
<div role="dialog" aria-modal="true" aria-labelledby="dlgTitle">
<h2 id="dlgTitle">Edit profile</h2>
…
</div>