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>