无法退出的焦点陷阱是阻断性缺陷
别名: 无法退出的陷阱 · inescapable focus trap · 键盘困住
概念解释
进得去、出不来,不是「焦点处理不够优雅」。对只使用键盘的人,无法退出的焦点陷阱(keyboard trap)等于产品停机:其余页面、其余任务、甚至浏览器的地址栏,都从操作集合里消失了。严重程度是阻断性的——一条任务走查在这里必须打终止,而不是记一条体验建议。
浮层把焦点关进自己内部可以是正确行为。这条只在门不存在、门在层内找不到、或按了门却没反应时成立。
机制
指针用户始终有一条物理逃逸:把指针移出组件去点别处,或点浏览器后退。键盘的逃逸必须由页面提供:Tab 循环要能离开,或 Escape / 关闭要把焦点送出组件。控件若在内部把 Tab、Escape 全部 preventDefault,又没有自己的离开命令,用户代理的导航键也被吞掉,人就被关在一个子树里。
嵌入的播放器、富文本编辑器、地图和支付 iframe 是典型制造者:它们为了「自己消化快捷键」截获全部按键,却没留「把焦点交还给宿主」的键。开关扫描用户的处境更硬——扫描焦点被锁在子树里时,连「移到浏览器控件」这条系统级退路都可能走不通。
怎么研究
判定标准只有一个:进入该区域之后,是否存在不依赖指针的离开方式,并在限定按键次数内成功离开。离开方式可以是 Tab 走到区域外、Escape、明确的「关闭」或「完成」。失败即阻断,不要按「还能用鼠标点外面」给部分分。
抽样优先覆盖第三方嵌入、视频播放器、自定义下拉保持打开的状态、全屏查看器。记录离开所需的键;若测试者最后伸手去点,记为陷阱成立。
边界
模态对话框在打开期间循环焦点,只要 Escape 或关闭能结束,就不是这条的陷阱。临时把焦点锁在画布里做一次连续操纵(例如用方向键挪对象)可以接受,但必须有文档化的退出键,且该键不能与「取消当前挪动」冲突到无法离开。浏览器扩展注入的层如果困住焦点,对用户仍是阻断——责任在整页体验,不能只测第一方代码。
怎么落地
- 任何会截获 Tab 或 Escape 的组件,必须另留一条离开命令,并在层内可见。
- 嵌入第三方播放器或编辑器前,用键盘走进去再试着走出来;走不出来就不要嵌,或在宿主侧提供「跳过此嵌入」的入口。
- 验证:键盘进入播放器、编辑器或打开的自定义列表,不碰指针,三十秒内回到页面其余部分。做不到,记为阻断性缺陷,不要排进「下个迭代优化」。