如何优雅地使背景元素不可获取焦点(Tab键及鼠标交互场景)
优雅实现模态窗口背景元素焦点隔离方案
1. 原生HTML属性 inert(推荐)
这是最简洁优雅的方案,直接给背景内容的容器添加inert属性,就能一次性让容器内所有元素:
- 无法通过鼠标点击、触摸触发交互
- 无法通过Tab键获取焦点
- 屏幕阅读器会自动忽略这些元素
示例代码:
<!-- 背景内容容器 --> <div id="background-content" inert> <button>背景按钮</button> <input type="text" placeholder="背景输入框"> <a href="#">背景链接</a> </div> <!-- 模态窗口 --> <div id="modal" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 2rem; background: white; border-radius: 4px; box-shadow: 0 2px 10px rgba(0,0,0,0.2);"> <h2>模态窗口</h2> <input type="text" placeholder="模态框输入框"> <button>确认操作</button> <button id="close-modal">关闭</button> </div> <script> // 关闭模态框时移除inert,恢复背景交互 document.getElementById('close-modal').addEventListener('click', () => { document.getElementById('background-content').removeAttribute('inert'); }); </script>
inert目前已被主流现代浏览器支持,无需额外兼容代码(如需适配极旧浏览器,可引入官方polyfill,但多数场景不需要)。
2. CSS批量控制可聚焦元素
如果暂时无法使用inert,可以通过给背景容器添加类,结合CSS选择器批量禁用焦点:
/* 模态框显示时,给背景容器添加这个类 */ .background-disabled { pointer-events: none; } .background-disabled :is(a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])) { tabindex: -1; /* 可选:视觉上提示元素不可交互 */ opacity: 0.6; }
这种方式不用逐个修改元素,但需要确保:is()选择器覆盖所有可聚焦元素类型。
3. 模态框焦点陷阱(配套优化)
为了交互完整性,模态框显示时建议实现焦点陷阱,确保Tab键始终在模态框内循环:
const modal = document.getElementById('modal'); const focusableElements = modal.querySelectorAll('button, input, select, textarea, a[href], [tabindex]:not([tabindex="-1"])'); const firstFocusable = focusableElements[0]; const lastFocusable = focusableElements[focusableElements.length - 1]; modal.addEventListener('keydown', (e) => { if (e.key === 'Tab') { if (e.shiftKey && document.activeElement === firstFocusable) { e.preventDefault(); lastFocusable.focus(); } else if (!e.shiftKey && document.activeElement === lastFocusable) { e.preventDefault(); firstFocusable.focus(); } } else if (e.key === 'Escape') { // 按ESC关闭模态框 document.getElementById('close-modal').click(); } }); // 模态框显示时自动聚焦到第一个可交互元素 firstFocusable.focus();
内容的提问来源于stack exchange,提问作者Sen
相关产品推荐
相关产品推荐

