inert 是唯一能同时切断鼠标、键盘、屏幕阅读器三端交互的原生方案,模态框开启时必须只给背景区域加 inert,而非整个 body,否则浮层(如 toast、loading)会一并失活。

inert 是唯一能同时切断鼠标、键盘、屏幕阅读器三端交互的原生方案,模态框开启时必须只给背景区域加 inert,而非整个 —— 否则浮层(如 toast、loading)会一并失活。
为什么不能直接给 加 inert
常见错误是“图省事”给 加 inert,结果导致所有子元素(包括模态框自身、全局提示、加载遮罩)全部被冻结:
-
<dialog></dialog>或自定义弹窗无法获得焦点,focus()失败 -
toast消息里的关闭按钮点不动,键盘 Tab 也跳不过去 - 滚动条消失(
inert不影响布局,但若你同时用了overflow: hidden就会卡住) - 辅助技术完全感知不到弹窗存在,违反 WCAG 2.1 A 级要求
正确 DOM 结构:背景内容区单独包裹
必须把可交互的浮层(<dialog></dialog>、<div role="alert">、<code><div class="loading">)放在 <code>inert 区域之外:
<div id="app"> <main id="main-content" inert></main><dialog open></dialog><div class="toast"></div> </div>
JS 控制逻辑只操作 mainContent.inert = isModalOpen,不碰 document.body。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- SSR 渲染时若服务端已输出
inert,客户端 hydration 后必须同步状态,否则 React/Vue 会报 “prop mismatch” - Astro 用户注意:
inert是 Astro 原生支持的布尔属性,无需额外配置,但 SSR 输出需与客户端一致 - 移动端 Safari 中,
inert不影响100vh高度错位问题——那是 viewport 行为,和inert无关
不支持 inert 的浏览器怎么兜底
Chrome 105+、Firefox 111+、Safari 16.4+ 原生支持;但 Safari 17 及更早版本、旧 Edge 完全忽略 inert。检测和降级必须手动做:
if ('inert' in HTMLElement.prototype) {
mainContent.inert = isModalOpen;
} else {
// 手动模拟:只处理可聚焦元素,不递归遍历全部子节点(性能差)
const focusables = mainContent.querySelectorAll('button, a[href], input, select, textarea, [tabindex]');
focusables.forEach(el => {
el.setAttribute('tabindex', isModalOpen ? '-1' : '');
if (isModalOpen) el.setAttribute('aria-disabled', 'true');
});
mainContent.style.pointerEvents = isModalOpen ? 'none' : '';
}
- 不要用
@webcomponents/inertpolyfill 替代逻辑判断——它在 Safari 17 下仍无法修复键盘焦点卡死问题 -
tabindex="-1"不等于禁用:它只是让元素退出 Tab 流,但click()和focus()依然有效,必须配合aria-disabled="true"提供语义 - 千万别用
pointer-events: none单独兜底——Tab 仍能聚焦其中的<button></button>,用户按回车就可能意外提交
容易被忽略的细节:焦点自动退出与恢复
inert 设为 true 时,若当前焦点在该区域内,浏览器会立即触发 blur 并尝试将焦点移到最近的可聚焦祖先或 。但这不是总能成功:
- 如果
本身不可聚焦(没设tabindex),焦点会丢失,键盘操作彻底中断 - 模态框打开后,应主动调用
dialogElement.focus(),且该元素需有tabindex="-1"(否则默认不可聚焦) - 关闭模态框后,
mainContent.inert = false不会自动恢复之前的焦点位置,需手动记录并 restore
真正难的不是加 inert,而是确保焦点链路始终可控——尤其当页面存在多个动态浮层时,DOM 层级和焦点管理必须严格对齐。










