Skip to content

dialog、modal 与返回焦点 ​

模态对话框打开后,键盘用户必须知道焦点在哪里、如何关闭,以及关闭后回到哪个控件。原生 <dialog> 能提供部分语义,但触发按钮和焦点恢复仍需要明确实现。

最小实验:保存并恢复焦点 ​

html
<button id="open">编辑标题</button>
<dialog id="editor">
  <form method="dialog">
    <label>标题 <input id="title" /></label>
    <button value="cancel">取消</button>
    <button value="save">保存</button>
  </form>
</dialog>
<script>
  const open = document.querySelector('#open')
  const dialog = document.querySelector('#editor')
  const title = document.querySelector('#title')
  let returnFocus
  open.addEventListener('click', () => {
    returnFocus = document.activeElement
    dialog.showModal()
    title.focus()
  })
  dialog.addEventListener('close', () => returnFocus?.focus())
</script>

点击“编辑标题”,按 Tab 检查焦点是否留在对话框内;按 Escape 关闭,确认焦点回到按钮。把 dialog.showModal() 改为 dialog.show(),比较背景可交互性和键盘行为。

机制与边界 ​

showModal() 创建模态 top layer,并使背景内容不可交互;close 事件只表示关闭完成,不会自动替你恢复业务焦点。删除触发按钮时要提供合理的后备焦点。真实项目还需用键盘任务和读屏工具验证名称、错误反馈和关闭方式。

练习 ​

  1. 增加表单校验错误,把错误消息与输入关联,并让焦点落到第一个错误控件。
  2. 测试用户在打开后按 Escape、点击取消和提交三条路径,记录返回焦点。
  3. 在旧浏览器不支持 <dialog> 时,说明降级到自定义模态层需要补齐哪些语义和焦点管理。

查看本节答案

用心记录每一步成长