页面加载时应只对主内容区设inert属性,浮层需置于其兄弟节点;inert必须用JS属性赋值而非setAttribute,SSR需同步输出inert属性,不支持浏览器需降级处理aria-hidden、tabIndex及focus重定向。

页面加载时直接锁点击,inert 不能用在 <body> 上——那样会连加载动画、全局 loading 遮罩、甚至 JS 错误提示都一起冻结,实际不可行。
只给主内容区加 inert,浮层必须放外层
真正能用的方案是:把可交互的浮层(如 loading、toast、模态框)放在 <main> 或 <div id="page-content"> 的兄弟节点位置,然后只对主内容容器设 inert:
<div id="app"> <main id="main-content" inert></main> <div class="loading-overlay"></div> <dialog></dialog> </div>
-
mainContent.inert = true立即退出当前焦点、阻止 click/keydown 冒泡、移出屏幕阅读器树 - 加载中若需显示 loading,它必须不在
inert区域内,否则用户看不到、点不了、也读不到 - 滚动仍可用(
inert不影响 scroll),但若滚动依赖<body>,得确认它没被意外加了inert
inert 必须用 JS 属性赋值,不是 setAttribute
动态控制时,写法错一点就完全失效:
- ✅ 正确:
document.getElementById('main-content').inert = true - ❌ 无效:
el.setAttribute('inert', '')、el.inert = 'true'、el.toggleAttribute('inert') - 浏览器只响应
element.inert = true/false这个 DOM 属性赋值,其他方式不会触发行为
SSR 和框架里必须同步初始状态
React/Vue 服务端渲染时,HTML 输出必须带 inert 属性,否则 hydration 阶段会报 “prop mismatch”:
立即学习“前端免费学习笔记(深入)”;
- 服务端输出:
<main id="main-content" inert> - 客户端 JS 初始化后,立刻执行:
mainContent.inert = isPageLoading - 如果首屏加载就锁交互,别等异步请求回来再设
inert——否则白屏期间用户仍可乱点
不支持的浏览器必须手动兜底
Safari 17.4 及更早、部分安卓 WebView 完全不识别 inert,polyfill(如 wicg-inert)只能模拟部分行为,无法补全焦点重定向和 AT 树移除:
- 检测:
if (!('inert' in HTMLElement.prototype)) - 降级至少做三件事:
element.setAttribute('aria-hidden', 'true')、element.tabIndex = -1、递归对所有可聚焦子元素(button、a[href]、input、[tabindex])设tabIndex = -1并监听focusin强制重定向 -
pointer-events: none单独撑不住——它挡不住 Tab、Enter 触发 click、或 JS 主动调用.focus()
真正容易被忽略的是:inert 不是“禁用按钮”,而是让那一整块 DOM 子树在浏览器眼里彻底“不存在于交互上下文”——焦点不会进去,事件不会冒泡,屏幕阅读器不会挂载。一旦忘了浮层要放外层、或 JS 写法错了、或 SSR 没同步,整个交互链就断了。



















