inert 不能用 css 替代,它是浏览器原生的 dom 层级交互隔离机制,直接让元素及其子树退出焦点流和可访问性树;必须作用于主内容区而非遮罩层或 body,且仅支持布尔值赋值(el.inert = true)。

inert 本身不管理 Tab 焦点流,它直接让整个子树退出焦点可访问性树——所以“锁定 Tab”不是它在做,而是它让 Tab 根本找不到目标。 你不需要手动拦截或重定向 Tab,只要正确应用 inert,浏览器就自动跳过被标记区域的所有可聚焦元素。
为什么给遮罩层(overlay)加 inert 是错的
遮罩层是模态框的一部分,必须保持可交互(比如点击关闭),但它背后的主内容区才是要冻结的对象。常见错误是:
- 把
inert加在<div class="overlay"> 上 → 遮罩层自己失活,用户点不了、Tab 不到、读屏器也感知不到 <li>给 <code>加inert→ 整个页面冻结,包括弹窗、toast、loading、甚至document.addEventListener('keydown')都收不到 ESC - 用
aria-hidden="true"替代inert→ Tab 仍能进入被隐藏的<input>,焦点卡住后无法离开
正确的 DOM 结构和 inert 控制方式
必须把可交互浮层(<dialog></dialog>、<div role="alert">、<code><div class="toast">)放在 <code>inert 区域之外,且只对主内容容器设 inert:
<main id="main-content" inert><p>这里是被冻结的内容</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5806" title="html-deploy"><img src="https://img.php.cn/upload/skill/000/000/081/179066538882434.jpg" alt="html-deploy" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill5806" title="html-deploy" class="overflowclass">html-deploy</a> <p class="overflowclass">使用 htmlcode.fun 将 HTML 内容或文件部署到网页,适用于用户要求“部署到网页”“托管此 HTML”“生成此前端...的实时链接”等场景。</p> </div> <a rel="nofollow" href="/xiazai/skill5806" title="html-deploy" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <button>这个按钮 Tab 不到了</button> </main><dialog open><h2>模态框标题</h2> <input type="text" autofocus></dialog><div class="toast">全局提示</div>
JS 控制必须用属性赋值,不是 setAttribute:
- ✅ 正确:
document.getElementById('main-content').inert = isModalOpen - ❌ 无效:
el.setAttribute('inert', '')、el.inert = 'true'(字符串值会被忽略) - ⚠️ SSR/框架注意:初始 HTML 必须含
inert属性,否则 React/Vue hydration 会报 prop mismatch
inert 失效时的典型表现和排查点
当发现 Tab 还能进入背景区域,说明 inert 没生效,优先检查以下几处:
- 是否误把浮层(如
<dialog></dialog>)嵌套在<main inert></main>内部?DOM 结构错误会导致它一并被冻结 - 是否在移动端触发了虚拟键盘?Safari 17.x 和部分安卓 WebView 中,
VirtualKeyboard.show()可能导致inert短暂松动,需监听virtualkeyboardchange事件并手动focus()回安全元素 - 是否用了 polyfill?WICG/inert 不处理焦点循环、不修复
Element.focus()主动调用,在 Safari 或 IE11 中需额外拦截并重定向 - 是否依赖
pointer-events: none单独撑场?它完全不影响 Tab,必须配合inert或兜底逻辑
真正容易被忽略的是:inert 不是 CSS 视觉开关,也不是事件拦截器——它是让浏览器彻底“看不见”那一块 DOM 子树的交互存在性。一旦写错位置或用错 API,它就完全静默失效,连控制台都不会报错。










