HTML inert 怎样暂时禁用背景区域交互
我在给一个带抽屉和确认弹窗的页面整理交互时,最容易漏掉的不是弹窗本身,而是弹窗打开以后,页面背景还可以被点击、按 Tab 聚焦,甚至继续被辅助技术读到。这个场景可以先用 HTML 的 inert 解决:给背景区域设置 inert,让它和所有后代暂时退出交互;浮层关闭后移除 inert,再把焦点恢复到触发控件。
一句话概括:inert 是“区域级”的交互开关,不是只禁用一个按钮的替代品。它会影响点击、聚焦、文本选择和辅助技术访问;视觉上的遮罩、焦点回收和不支持环境的降级仍然需要开发者补齐。
先划分浮层与背景的交互边界
一个稳定的模态交互通常有两个兄弟区域:页面背景负责展示原内容,模态对话框负责当前任务。打开模态内容时,背景应该暂时不能参与交互;关闭后,背景重新可用。inert 最适合放在背景容器上,而不是随手加在 body 或单个链接上。

下面这段结构把“背景”和“当前任务”分开,后面的 JavaScript 只需要切换背景容器的状态:
帮助文档
这里的关键不是元素名字,而是边界清楚:将来页面增加导航、表单或异步提示时,只要它们仍在 main 内,就会跟随背景状态统一处理。
用 inert 暂停背景区域
inert 是布尔全局属性。它存在时,元素及其扁平树后代不能获得焦点,也不会触发普通的点击和聚焦事件;内容还会从辅助技术访问树中排除。对模态层来说,这比逐个给按钮加 disabled 更接近真正的“背景暂停”。
const pageContent = document.querySelector('#page-content');
const settingsDialog = document.querySelector('#settings-dialog');
const openButton = document.querySelector('#open-settings');
openButton.addEventListener('click', () => {
// 先暂停背景,再打开当前任务,避免切换瞬间仍可操作页面内容。
pageContent.inert = true;
settingsDialog.showModal();
});
// HTMLElement.inert 与 HTML 属性 inert 表达的是同一个状态。
为了让用户能看出当前状态,还要配合遮罩或明确的视觉层级。inert 本身不会自动把背景变暗,也不会自动告诉用户为什么暂时不能操作;可见提示和真实交互状态要保持一致。
body:has(#settings-dialog[open]) #page-content {
/* 视觉提示只表达背景暂不可操作,不代替 inert 的语义效果。 */
opacity: 0.55;
filter: saturate(0.7);
}
#settings-dialog::backdrop {
/* 遮罩把当前任务和背景分开,颜色不要遮住对话框内容。 */
background: rgb(15 23 42 / 0.42);
}
如果只是单个表单控件暂时不能使用,优先考虑 HTML 的 disabled;inert 更适合一整块内容,例如导航区、页面主体或抽屉背后的区域。
关闭浮层后怎样恢复交互
背景暂停和恢复必须成对出现。关闭对话框时移除 inert,并将焦点送回原来的打开按钮,键盘用户才不会突然失去位置。恢复动作应该挂在同一个关闭路径上,包含关闭按钮、取消动作和用户按 Esc 的情况。

function restorePage() {
// 先恢复背景语义,再把键盘焦点送回用户刚才触发的位置。
pageContent.inert = false;
openButton.focus();
}
document.querySelector('#close-settings').addEventListener('click', () => {
// close 会结束 dialog 的模态状态,恢复动作保证背景不会一直锁住。
settingsDialog.close();
restorePage();
});
settingsDialog.addEventListener('cancel', (event) => {
// cancel 对应用户按下 Esc;保留浏览器默认关闭行为后再恢复背景。
event.preventDefault();
settingsDialog.close();
restorePage();
});
如果关闭后还要刷新列表或显示提交结果,建议先完成 close()、inert = false 和焦点恢复,再处理后续提示。这样即使后续请求失败,页面也不会因为等待请求而保持“背景锁死”。
可访问性上要特别注意什么
我第一次使用 inert 时,以为它会顺便完成全部模态可访问性工作,后来发现它解决的是背景边界,不是完整的对话框设计。对话框仍然要有可读的名称,关闭后要有明确的焦点去向,背景状态也最好有颜色、遮罩或说明文本提示。
原生 通过 showModal() 打开时具有特殊的模态行为;它可以脱离祖先的 inert 影响,但其他普通元素不能随意“逃出”背景的 inert 状态。不要把这个例外理解成所有自定义浮层都能自动获得同样的焦点管理。
还有一个容易忽视的点:inert 没有默认的视觉表现。只设置属性、不加遮罩或状态提示,用户可能只觉得页面“突然失灵”。视觉线索不能替代语义属性,但两者应该同时存在。
旧浏览器怎样保留降级方案
MDN 当前把 inert 标记为广泛可用,但实际项目仍可能需要照顾旧设备或嵌入式 WebView。我的做法是把基础布局和关闭逻辑先写成可用版本,再用 @supports 增强;不支持时至少保留遮罩、关闭按钮和手动的焦点策略。
.modal-backdrop {
/* 基础样式让旧环境仍能区分当前浮层和背景。 */
position: fixed;
inset: 0;
background: rgb(15 23 42 / 0.42);
}
@supports (inert: true) {
/* 支持 inert 时让语义状态负责阻止背景交互。 */
#page-content[inert] {
pointer-events: none;
}
}
需要说明的是,pointer-events: none 只能覆盖鼠标或触摸命中,不能代替 inert 对焦点和辅助技术访问树的处理。旧环境如果没有 inert,应该结合移除背景中的可聚焦入口、保存并恢复焦点等策略,而不是只加一层透明遮罩。
我的结论:用 inert 管区域,用 dialog 管当前任务
如果你要实现模态框、抽屉或全屏确认层,可以把职责拆开:背景容器用 inert 暂停, 或浮层容器承载当前任务,关闭时恢复 inert 并回收焦点,视觉层用遮罩解释状态,@supports 为旧环境准备降级。
对我来说,inert 最实用的地方不是少写一个点击拦截器,而是把“这整块区域暂时不属于当前交互”表达成了原生语义。它适合区域级暂停;如果只是禁用一个输入框,仍然应该使用更具体的 disabled。
常见问题
inert 会自动显示遮罩吗?
不会。它负责交互和辅助技术边界,不提供默认的视觉效果。遮罩、透明度、提示文本和层级样式需要自行设计。
给 body 设置 inert 可以吗?
通常不建议。更稳妥的做法是把背景内容放进明确的容器,只暂停该容器;浮层和需要继续工作的全局提示不应被误伤。
inert 和 disabled 有什么区别?
disabled 主要针对单个表单控件或控件组;inert 面向一整块元素及其后代,还会影响焦点、点击和辅助技术访问树。
把背景边界、焦点恢复、视觉提示和兼容回退一起考虑,模态交互才不会只“看起来打开了”,而是真的把当前任务交给用户。
CSS field-sizing 怎样让文本框高度随内容变化
- 上一篇
- CSS field-sizing 怎样让文本框高度随内容变化
- 下一篇
- ARIA live 怎样播报异步状态变化
-
- 文章 · 前端 | 1小时前 |
- ARIA live 怎样播报异步状态变化
- 261浏览 收藏
-
- 文章 · 前端 | 1小时前 | css · 表单 · 表单布局 CSS field-sizing 文本框自适应 textarea 自动高度
- CSS field-sizing 怎样让文本框高度随内容变化
- 328浏览 收藏
-
- 文章 · 前端 | 1小时前 | css ·
- CSS 容器查询怎样按组件宽度切换布局
- 330浏览 收藏
-
- 文章 · 前端 | 1小时前 |
- Service Worker 更新怎样控制接管时机
- 486浏览 收藏
-
- 文章 · 前端 | 1小时前 | 前端 · javascript · request Cache API Cache.match Vary
- Cache API 怎样用完整请求区分缓存条目
- 432浏览 收藏
-
- 文章 · 前端 | 1小时前 |
- IndexedDB 数据库升级怎样处理版本变更
- 483浏览 收藏
-
- 文章 · 前端 | 1小时前 |
- Web Worker 怎样转移 ArrayBuffer 避免复制
- 408浏览 收藏
-
- 文章 · 前端 | 1小时前 | 前端 · javascript · AbortController ReadableStream Streams API
- ReadableStream 取消后怎样释放请求
- 203浏览 收藏
-
- 文章 · 前端 | 1小时前 | javascript · 前端工程 · ReadableStream 流式响应 TransformStream pipeThrough Streams API
- ReadableStream 怎样用 TransformStream 转换数据
- 151浏览 收藏
-
- 文章 · 前端 | 1小时前 |
- Fetch 怎样用 AbortSignal.timeout 设置请求超时
- 166浏览 收藏
-
- 文章 · 前端 | 1小时前 |
- Fetch keepalive 适合发送哪些小请求
- 397浏览 收藏
-
- 文章 · 前端 | 16小时前 |
- 前端 source map 发布怎样保护源码边界
- 194浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 478次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 535次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 554次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 506次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 327次使用
-
- 移动端输入框聚焦后按钮被键盘挡住怎么办:用 visualViewport 做底部适配
- 2026-06-29 424浏览
-
- golang解析html网页的方法
- 2022-12-29 132浏览
-
- Go text/template与html/template选择输出边界的对比
- 2026-09-23 275浏览
-
- Go html/template 怎样区分文本和 HTML 内容
- 2026-10-14 281浏览
-
- 这样需求的表单一般要这么做?
- 2023-02-17 194浏览
