写过 UI 的人都踩过这个坑——弹窗打开之后背后的内容总得写一堆 JS,今天 inert 一个属性把这件事彻底原生化了
写过 UI 的人都踩过这个坑——弹窗打开之后背后的内容,要禁按钮、拦输入框、挡点击,全靠自己一行一行写 JS 去加 disabled 或者盖遮罩。2023 年浏览器全面支持的 inert 属性,一行 HTML 把这件事彻底原生化了。
inert 是什么
inert 是一个 HTML 全局属性,写上去之后这个元素和它的所有子树全部变成非交互状态:
- 按钮点不了、输入框收不到焦点
- 链接按不了、表单控件完全是死的
- 文字选不了、页面内搜索也搜不到这块内容
- 读屏软件直接跳过这一整块
重点是:不是一行一行禁用的,是浏览器帮你把整个子树一次性“冻结”了。
核心场景:模态对话框
这是 inert 最大的用武之地。
打开对话框时,给背景层加 inert:inert 之后,背景层的所有交互被浏览器自动屏蔽——不需要 JS、不需要遮罩、不需要逐个加 disabled。
关闭弹窗时移除属性:main.removeAttribute("inert");
背景立刻恢复交互。
inert vs disabled vs aria-hidden
这三个都和“禁用”有关,但完全不同:
| 属性 | 作用范围 | 视觉 | 读屏 |
|---|---|---|---|
disabled |
表单控件 | 灰显 | 暴露但不可交互 |
aria-hidden="true" |
任意元素 | 无变化 | 隐藏 |
inert |
任意元素+子树 | 无变化(需自己加样式) | 隐藏且不可交互 |
inert 是唯一一个同时做到:完全阻止交互 + 从可访问性树移除 + 阻止页面内搜索 的属性。
浏览器支持
2023 年 4 月全面支持:
- Chrome 102+、Firefox 112+、Safari 15.5+
- 移动端全部支持
- 全球覆盖率 95%+
生产环境直接用,无需 polyfill。
降级方案
inert 本身没有默认视觉,被禁用区域外观不变。需要自己加样式:
[inert] {
opacity: 0.5;
pointer-events: none;
}
这是旧浏览器的降级,也是给用户的视觉提示。
实际用法
模态对话框——打开时给背景加 inert,关闭时移除。对话框本身如果是 showModal() 创建的,浏览器已经自动处理,不需要手动加。
多步骤表单——用户填完第一步,把后续步骤区域设为 inert,防止跳步填写。第二步提交后,给第三步加 inert、同时解除第二步。
折叠面板/标签页——隐藏的面板不需要 display: none,直接加 inert,保留 DOM 结构的同时完全禁用交互,比 visibility: hidden 更干净。
什么时候用 inert
- 弹窗用的是
showModal()→ 浏览器已经自动处理,不需要手动加inert - 弹窗用的是
show()或者自己写的遮罩方案 → 手动给背景加inert - 需要精确控制禁用范围的任何情况 →
inert
一个需要注意的细节:inert 是离散型(discrete)过渡,不支持平滑过渡到 display: none。如果你的弹窗有动画关闭效果,inert 本身的添加/移除没有过渡,但配合 CSS 动画可以达到不错的效果。
下一步
去你的代码库搜索这三类场景:
- 手动给多个按钮加
disabled的弹窗背景处理代码 - 用遮罩 div +
pointer-events: none做的弹窗背景 - 用
aria-hidden凑合的禁用方案
这三类场景,都可以重构成一行 inert。这是今年最值得重写的三行代码之一。
评论区
登录后可评论。