inert属性必须加在非模态区域容器(如或)上,弹窗等浮层须与其同级或更高层级;不能加在上,否则浮层交互与可访问性全失效。

inert 属性加在哪才能真正防住误点
不能直接给 加 inert,否则 toast、loading 遮罩、全局快捷键等浮层全被锁死。正确做法是只对非模态区域的容器设 inert,比如 <main id="app-content"></main> 或 <div id="page-body">,而把弹窗、提示框这些元素放在它 DOM 外层(同级或更高层级)。
<p>常见错误:用 SSR 渲染时服务端已输出 <code>inert,但客户端 hydration 没同步状态,React/Vue 会报 prop mismatch,导致首次交互失效。
- 模态框开启时,只执行
mainContent.inert = true,不要碰document.body - 确保浮层(如
<div class="toast">)不在 <code>mainContent内部,DOM 结构必须是平级或父级 - SSR 框架中,初始 HTML 要和 JS 状态一致,否则 hydration 后
inert可能被框架强制移除 - 启用:
document.getElementById('app-content').inert = true - 关闭:
document.getElementById('app-content').inert = false - 检查支持:
'inert' in HTMLElement.prototype,不支持时得手动兜底 - 动态插入的新节点(比如 Vue 组件重渲染新增的
<div inert>),polyfill 不会自动处理,需显式调用 <code>inert.apply(element)为什么按钮看起来还能点,但实际点不动
inert不改样式,按钮视觉上仍是默认状态,用户看到“可点击”却点无效,极易困惑。必须配合 CSS 主动灰掉:div[inert] button, div[inert] input, div[inert] a { opacity: 0.5; pointer-events: none; user-select: none; }注意:仅靠
pointer-events: none不够,它拦不住键盘焦点;inert才是真正切断焦点链路的机制。CSS 只是视觉反馈,不能替代inert的语义作用。- 别用
disabled替代 —— 它只适用于表单控件,且会改变提交行为 - 别混用
aria-hidden="true"—— 它只影响读屏器,不阻 Tab 键,反而造成可访问性矛盾 - 移动端虚拟键盘弹出时,Safari 17.x 可能短暂忽略
inert状态,需额外监听resize或focusin做二次校验
旧浏览器没 inert 怎么安全降级
Chrome 111+、Firefox 121+、Safari 18.0+ 原生支持;Safari 17.x 及更早、部分旧 Edge 完全不识别
inert,且 polyfill(如@webcomponents/inert)无法完美模拟焦点退出和事件截断。兜底策略必须手动逐层处理,没有 magic 方案:
- 遍历所有可聚焦元素(
button、a[href]、input、[tabindex]),统一设tabIndex = -1 - 容器加
pointer-events: none+user-select: none - 设
aria-disabled="true"提供辅助技术语义,但别依赖它阻交互 - 监听
focusin,检测焦点是否落入禁用区域,强制focus()到模态框首个按钮
真正容易被忽略的是:inert 不是样式开关,也不是事件拦截器,它是 DOM 层级的“存在性开关”——一旦启用,那个子树在浏览器眼里就相当于不存在于交互和可访问性上下文中。降级方案永远只能逼近,无法完全复现。
- 别用
动态启用 inert 时 JS 怎么写才不踩坑
inert 是布尔属性,不是字符串值,JS 控制必须用 .inert = true/false,写成 setAttribute('inert', 'true') 或 removeAttribute('inert') 完全无效——浏览器根本不认。
另外,inert 启用后,当前聚焦的元素会自动 blur,但不会触发 blur 事件,别指望靠监听它做清理逻辑;如果元素本身有 tabindex,inert 会覆盖它,无需手动重置。











