inert属性必须写在要冻结的容器上,用.inert = true/false控制,浮层须为其兄弟节点;错误加在body或遮罩层、用setattribute均无效,不支持浏览器需手动兜底。

直接写 inert 就生效,不用值、不靠 CSS、不依赖事件拦截;但加错位置或用错 JS 写法,它就完全不工作。
inert 属性必须写在要冻结的容器上,不能写在遮罩层或 body 上
常见错误是把 inert 加在 <div class="overlay"> 或 <code> 上——前者让遮罩自己失活(点不了关闭按钮),后者连 <dialog></dialog>、<toast></toast> 全被锁死。
- ✅ 正确做法:用一个独立容器包裹主内容,比如
<main id="main-content" inert></main> - ✅ 浮层必须是它的兄弟节点:
<dialog></dialog>、<div class="toast"> 都得放在 <code><main></main>外面 - ❌ 错误结构:
<main inert><dialog>...</dialog></main>→ 弹窗一并被冻结 - ⚠️ 注意:滚动容器如果是
<main></main>自身,inert不影响滚动能力;但若靠滚动,就得确保没被误冻 - ✅ 正确:
document.getElementById('main-content').inert = isModalOpen—— 立即退出焦点、跳过 Tab、移出可访问性树 - ❌ 无效:
el.setAttribute('inert', '')、el.inert = 'true'、el.toggleAttribute('inert') - ⚠️ SSR/框架场景:服务端 HTML 必须已含
inert属性,否则 React/Vue hydration 会报prop mismatch - ⚠️ 动态插入的新节点(如 Vue 组件重渲染后新增的
<div inert>)polyfill 不自动接管,需手动调用 <code>inert.apply(el)不支持 inert 的浏览器必须手动兜底,polyfill 不等于“完全兼容”
Chrome 111+、Firefox 121+、Safari 18.0+ 原生支持;Safari 17.x 及更早、旧 Edge、部分安卓 WebView 完全无视
inert,且 polyfill(如@webcomponents/inert)无法模拟焦点退出和 AT 树移除。- ✅ 检测方式:
if ('inert' in HTMLElement.prototype) - ✅ 降级至少三件事:对目标容器设
aria-hidden="true"+tabIndex = -1;递归遍历所有可聚焦子元素(button、a[href]、input、[tabindex])并设tabIndex = -1;加pointer-events: none和user-select: none - ❌ 不要只靠
pointer-events: none或display: none—— 它们挡不住 Tab 进入、Enter 触发 click、或 JS 主动.focus() - ⚠️ 特别注意:移动端虚拟键盘弹出时(如
input聚焦),Safari 17.x 可能导致inert短暂松动,需监听virtualkeyboardchange并手动focus()回安全元素
真正容易被忽略的是:
inert不是“视觉禁用”,也不是“事件拦截”,它是让浏览器彻底“看不见”那一块 DOM 子树的交互与语义存在——所以结构错、赋值错、兜底漏,它就形同虚设。 - ✅ 检测方式:
JS 控制 inert 必须用 .inert = true/false,不能用 setAttribute
inert 是布尔属性,浏览器只认 JS 属性赋值,setAttribute、removeAttribute、字符串赋值全无效。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。










