inert属性必须直接写为<element inert>,不带值、不加引号,JS动态控制只能用.inert = true/false,不可用setAttribute;给<body>加inert会连同弹窗一并禁用,正确做法是将弹窗置于被inert元素的同级外层,且旧浏览器需降级处理。

inert属性怎么写才生效
直接在目标容器上写inert布尔属性,不带值、不加引号、不赋字符串——写了就禁用,删了就恢复。浏览器只认“有无”,不认inert=""或inert="true"这种写法,后者完全无效。
常见错误:<div inert="true"> 或 <button inert=""> —— 这些 DOM 属性存在,但行为零响应。正确写法只有:<main inert>、<div id="page-content" inert>。
它不影响样式、布局、滚动或渲染,只是让浏览器从交互链路和可访问性树中彻底“忽略”该元素及其所有子节点。
JS动态控制必须用.inert = true/false
不能用setAttribute、removeAttribute或toggleAttribute操作inert——这些调用对行为毫无影响。唯一可靠方式是直接赋值 DOM 元素的inert属性:
立即学习“前端免费学习笔记(深入)”;
-
mainContent.inert = true:立即退出当前焦点(如果有的话),阻止click/keydown事件冒泡进子树,移出屏幕阅读器可访问性树 -
mainContent.inert = false:恢复全部交互能力,包括重新参与 Tab 顺序(但不会自动聚焦回来) - 若用 React/Vue,SSR 输出的 HTML 必须初始含
inert属性,否则 hydration 时触发“prop mismatch”警告
为什么不能给<body>加inert
给<body>加inert会锁死整个页面,包括本该可用的浮层:<dialog>、<toast>、全局 loading 遮罩、键盘快捷键监听器(如document.addEventListener('keydown', ...))全失效。
正确结构必须是浮层与被禁用区域为兄弟节点,例如:
<div id="app"> <main id="main-content" inert></main> <dialog open></dialog> <div class="toast"></div> </div>
JS 只控制mainContent.inert = isModalOpen,<dialog>和<toast>必须在<main>外层,不能嵌套其中。
旧浏览器兜底不是可选项,而是必做项
Chrome 111+、Firefox 121+、Safari 18.0+ 原生支持inert;Safari 17 及更早、部分安卓 WebView 完全不识别,且 polyfill(如 WICG/inert)无法 100% 补齐键盘焦点流重定向和 AT 树移除。
检测和降级建议:
- 先判断:
if ('inert' in HTMLElement.prototype) - 不支持时,至少三件事并行:
aria-hidden="true"+tabIndex = -1(父容器) +pointer-events: none - 遍历可聚焦元素要完整:
button, a[href], input:not([type="hidden"]), select, textarea, [tabindex]:not([tabindex="-1"]),别漏掉details或自定义role="button" - 别依赖
pointer-events: none单独撑场——它挡不住 Tab 进入、Enter 触发 click,也拦不住 JS 主动调用.focus()
真正容易被忽略的是:inert不是视觉隐藏,也不是事件拦截,它是让浏览器引擎在 DOM 层级“看不见”那一块子树的交互存在性——这个语义层级,CSS 和 JS 模拟永远差一层。



















