检测用'inert' in HTMLElement.prototype;Safari 17.x等不支持,Chrome 111+/Firefox 121+/Safari 18.0+稳定支持;polyfill可模拟禁用焦点与事件,但无法修改可访问性树、重定向Tab流或处理shadow DOM。

不支持inert的浏览器怎么检测
先确认当前环境是否原生支持,不能靠 UA 判断,必须用特性检测:'inert' in HTMLElement.prototype。Safari 17.x、旧 Edge、部分安卓 WebView 和所有 IE 都会返回 false。Chrome 111+、Firefox 121+、Safari 18.0+ 才稳定支持——注意 Safari 18.0 是 macOS Sequoia 和 iOS 18 的起始版本,17.x 仍需兜底。
polyfill 能做什么、不能做什么
官方 @webcomponents/inert(或 wicg-inert)是目前最可靠的 polyfill,但它不是“全功能替代”:
- ✅ 模拟
element.inert = true行为:设tabIndex = -1、加pointer-events: none、递归禁用子元素焦点 - ✅ 拦截鼠标/触摸事件(通过事件委托 +
stopPropagation) - ❌ 不修改可访问性树:
aria-hidden="true"是它唯一能做的语义补全,但屏幕阅读器仍可能读出内容 - ❌ 不重定向 Tab 焦点流:浏览器原生 tab order 不变,只能靠
focusin监听 + 强制.focus()到安全元素 - ❌ 不处理 shadow DOM 内部:若 inert 元素含自定义组件,polyfill 不自动穿透
加载 polyfill 必须在业务 JS 执行前、且不能带 async 或 defer —— 否则首次 el.inert = true 可能被忽略。
手动兜底必须做的三件事
如果不想引入 polyfill,或需要更高控制粒度,得自己实现最小可行降级:
立即学习“前端免费学习笔记(深入)”;
- 对目标容器设
element.setAttribute('aria-hidden', 'true')和element.tabIndex = -1 - 递归查找所有可聚焦子元素:
button, [href], input:not([type="hidden"]), select, textarea, [tabindex]:not([tabindex="-1"]), [role="button"], [role="link"],逐个设el.tabIndex = -1 - 监听
focusin事件,一旦焦点落入该区域,立刻event.preventDefault()并safeElement.focus()(如模态框第一个按钮)
别漏掉 details、summary 和自定义 role 元素——它们常被 querySelectorAll('button, input, a') 漏掉。
动态插入节点时容易忽略的点
React/Vue 组件重渲染、innerHTML 插入、或 document.createElement 新增的元素,即使带 inert 属性,polyfill 也不会自动接管——必须显式调用 inert.apply(el)(polyfill 提供的 API)。原生 inert 属性也一样:新节点挂载后,得手动赋值 newEl.inert = true,否则无效。
真正容易被忽略的是:inert 的“冻结”是 DOM 子树级的存在性开关,不是样式或事件层补丁;兼容性兜底做不到 100% 语义等价,尤其在辅助技术路径上,必须接受“降级 ≠ 等效”。



















