YL

ACCESSIBILITY

焦点锁定Focus Trap

弹窗打开后,Tab 只在弹窗内循环,不会跑到背后的页面上;关闭后焦点回到触发元素。弹窗可用性的底线。

效果预览

删除这个项目?

此操作不可撤销,相关的 12 个页面也会一并移除。

取消确认删除

适合用在哪

所有模态对话框、抽屉、全屏浮层。

容易踩的坑

  • 关闭弹窗后不把焦点还给触发按钮,键盘用户被丢回页面顶部重新 Tab。
  • 只锁 Tab 不处理 Shift+Tab,反向导航时焦点直接逃到背景页面。
  • 弹窗内容异步加载后才出现可聚焦元素,初始聚焦落空,Tab 循环失效。

设计提示词 · Prompt

焦点锁定(Focus Trap):打开弹窗时 —— ① 弹窗根元素加 role="dialog" aria-modal="true" 与 aria-labelledby 指向标题;② 记录当前 document.activeElement(触发元素);③ 把焦点移到弹窗内第一个可聚焦元素(或弹窗容器本身 tabindex="-1");④ 监听 keydown 的 Tab:若当前在最后一个可聚焦元素且按 Tab,则把焦点循环到第一个(Shift+Tab 反向同理);⑤ 关闭时把焦点还原给之前记录的触发元素。同时禁止背景滚动(body overflow:hidden,注意保留滚动条宽度避免跳动)并支持 Esc 关闭。成熟做法可用 focus-trap、Radix Dialog 等库。
Focus Trap: when opening a dialog — 1) add role="dialog" aria-modal="true" to the dialog root, with aria-labelledby pointing to its title; 2) record the current document.activeElement (the trigger); 3) move focus to the first focusable element inside the dialog (or to the dialog container itself with tabindex="-1"); 4) listen for Tab keydown: if focus is on the last focusable element and Tab is pressed, cycle focus back to the first (Shift+Tab works in reverse); 5) on close, restore focus to the recorded trigger. Also prevent background scrolling (body overflow:hidden, preserving scrollbar width to avoid layout jumps) and support Esc to close. Mature options include libraries like focus-trap and Radix Dialog.

常见搭配

同一页面里经常和「焦点锁定」一起出现的模式,可以收藏后用「组合收藏为整页提示词」一起交给 AI。

演示 HTML 结构

<div class="s d-center">
  <div class="a11y-trap">
    <div class="a11y-trap__m">
      <b>删除这个项目?</b>
      <p>此操作不可撤销,相关的 12 个页面也会一并移除。</p>
      <div class="a11y-trap__b"><i class="is-focus">取消</i><i class="is-p">确认删除</i></div>
    </div>
  </div>
</div>

标签