写过 UI 的人都踩过这个坑——弹窗打开之后背后的内容总得写一堆 JS,今天 inert 一个属性把这件事彻底原生化了

写过 UI 的人都踩过这个坑——弹窗打开之后背后的内容,要禁按钮、拦输入框、挡点击,全靠自己一行一行写 JS 去加 disabled 或者盖遮罩。2023 年浏览器全面支持的 inert 属性,一行 HTML 把这件事彻底原生化了。

inert 是什么

inert 是一个 HTML 全局属性,写上去之后这个元素和它的所有子树全部变成非交互状态:

  • 按钮点不了、输入框收不到焦点
  • 链接按不了、表单控件完全是死的
  • 文字选不了、页面内搜索也搜不到这块内容
  • 读屏软件直接跳过这一整块

重点是:不是一行一行禁用的,是浏览器帮你把整个子树一次性“冻结”了。

核心场景:模态对话框

这是 inert 最大的用武之地。

打开对话框时,给背景层加 inertinert 之后,背景层的所有交互被浏览器自动屏蔽——不需要 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 动画可以达到不错的效果。

下一步

去你的代码库搜索这三类场景:

  1. 手动给多个按钮加 disabled 的弹窗背景处理代码
  2. 用遮罩 div + pointer-events: none 做的弹窗背景
  3. aria-hidden 凑合的禁用方案

这三类场景,都可以重构成一行 inert。这是今年最值得重写的三行代码之一。

评论区

0 条评论

登录后可评论。