inert冻结交互但保留布局,hidden移除可见性且影响渲染;inert递归禁用子元素的焦点、鼠标和读屏访问,hidden仅语义隐藏并从渲染流中移除元素。

inert 和 hidden 都写在标签上,但浏览器处理方式完全不同
两者都是布尔属性,写上就生效,但作用域和底层机制完全不是一回事。inert 是“冻结交互”,hidden 是“移除可见性”。关键区别不在视觉表现,而在 DOM 行为、焦点流和辅助技术链路。
inert 会切断键盘 Tab、鼠标点击、屏幕阅读器访问,但元素仍渲染占位
加了 inert 的 <div> 里的 <code><button></button> 点不了、Tab 进不去、NVDA/JAWS 不会读——但它还在页面里,尺寸、边距、盒模型全保留,不影响周围布局。
-
inert对子元素递归生效,无需逐个加tabindex="-1"或aria-hidden="true" - 它不等价于
pointer-events: none+tabindex="-1"组合:后者无法阻止屏幕阅读器聚焦到禁用区域内的可聚焦子节点 - Chrome 102+、Firefox 125+、Safari 16.4+ 已支持;旧版需 polyfill(如
wicg-inert)
hidden 只做语义隐藏,不影响交互能力
hidden 的本质是告诉浏览器:“这段内容当前对所有用户都不相关”,效果接近 display: none,但它是 HTML 原生语义开关。它会被屏幕阅读器忽略,也会从渲染流中移除——所以父容器会重排,offsetHeight 返回 0。
-
hidden不影响子元素的tabindex或事件监听器;如果子元素本身有tabindex="0",且你没手动禁用,它仍可能被聚焦(尽管看不见) - 不能靠 CSS 覆盖
hidden效果,除非用!important强制改display,否则样式层面对它无效 - 别和
aria-hidden="true"混用:aria-hidden只屏蔽辅助技术,视觉上仍显示、仍可点、仍可 Tab 进去
选哪个?看你要解决的是“看不见”还是“碰不到”
弹窗打开时想锁住背景页?用 inert —— 它能同时拦住鼠标、键盘、读屏器,且不破坏布局流;只是临时藏一个图标或表单字段?用 hidden 更轻量、语义准确。
- 需要 DOM 存在但禁止一切用户输入 → 选
inert - 需要彻底移出渲染、节省重排开销、且确定不需要后续交互 → 选
hidden - 用
visibility: hidden或opacity: 0代替它们?危险:前者仍可点击、后者仍可 Tab,都不是真正的“禁用”
真正容易被忽略的,是 inert 对焦点管理的隐式影响:它会自动从可访问性树和 tab 顺序中剔除整块子树,而开发者常以为加个 tabindex="-1" 就够了——其实不够,尤其对屏幕阅读器用户。











