Chrome按Tab键强制聚焦屏外元素破坏页面布局的解决方案问询
问题根因
Chrome 内置的可访问性逻辑会自动将获得焦点的元素滚动到视口范围内,使用 transform: translate 仅能将抽屉在视觉上偏移出视口,不会改变抽屉内部可聚焦元素的焦点触发逻辑,因此Tab键选中抽屉内部元素时会触发自动滚动,导致布局偏移。
推荐解决方案:使用
inert 原生属性 这是目前成本最低、适配性最好的实现方案,完全符合需求:
- 核心特性:
inert是HTML原生提供的属性,被标记为inert的元素及其所有子元素会被完全排除在交互链外:无法通过Tab键聚焦、无法响应鼠标/键盘事件、也不会被屏幕阅读器识别,同时完全不会影响元素的视觉渲染效果。 - 实现逻辑:
- 抽屉打开状态下移除
inert属性,保证内部内容可正常交互 - 触发抽屉关闭操作的第一时间就为抽屉容器添加
inert属性,此时关闭动画仍可正常播放,但内部元素已经无法被聚焦,彻底避免Tab键触发的问题 - 关闭动画执行完成后,再添加
visibility: hidden属性做性能优化即可
- 抽屉打开状态下移除
- 优势:无需遍历修改抽屉内的任意子元素,自动适配任意数量的内部内容,代码维护成本极低,现代浏览器均已支持该属性。
兼容旧浏览器备选方案:焦点拦截
如果需要兼容不支持inert的旧版本浏览器,可以通过全局焦点拦截实现相同效果:
- 实现逻辑:
- 给抽屉容器添加状态标记,比如
data-state,可选值为open/closing/closed - 全局监听
focusin事件,当焦点落到状态为closing或closed的抽屉内部时,主动将焦点转移到抽屉开关按钮等外部合法可聚焦元素上
- 给抽屉容器添加状态标记,比如
- 代码示例:
document.addEventListener('focusin', (e) => { const drawer = document.querySelector('.drawer') if (!drawer) return const state = drawer.dataset.state if (state === 'closing' || state === 'closed') { if (drawer.contains(e.target)) { // 焦点转移到抽屉开关按钮 document.querySelector('.drawer-toggle').focus() } } })
内容的提问来源于stack exchange,提问作者Ryan Odd
相关产品推荐
相关产品推荐

