HTML inert 属性怎样让模态框外内容不可交互
模态框打开时,背景区域不能只靠半透明遮罩“看起来不能点”。更稳妥的做法是把背景根节点设为 inert,让它及其后代不能获得焦点、响应点击,也不会继续出现在辅助技术的交互路径中。关闭模态框时再把 HTMLElement.inert 恢复为 false。
官方资料:https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inert
如果页面使用原生并通过showModal()打开,浏览器会让对话框外的文档内容自动处于 inert 状态;如果是自定义遮罩层,就需要自己把背景容器切换为inert。
先分清遮罩层和 inert 状态
遮罩层只负责视觉反馈,例如压暗背景、阻止鼠标落到背景上的一部分区域;它不会自动改变键盘 Tab 顺序,也不会让背景按钮从辅助技术的可访问树中消失。inert 是交互状态:元素和它的 flat tree 后代不能聚焦、不能触发点击事件,通常也不能被页面查找、选中文本或通过辅助技术操作。

因此,先把“用户看不见”与“用户不能交互”分开处理:遮罩负责颜色和层级,inert 负责交互边界,模态框自身负责焦点进入与退出。
把背景内容包成一个可切换的根节点
自定义模态框最容易维护的结构,是让正文和导航共用一个背景根节点,弹窗放在它的外层。这样只需要切换一个属性,不必逐个给按钮加 disabled。
编辑资料
这里的关键不是 role 本身,而是页面背景拥有稳定的 DOM 边界。后续 JavaScript 可以统一写入 page-shell.inert,弹窗关闭后再恢复。
用 HTMLElement.inert 切换模态框外内容
HTMLElement.inert 是布尔属性:设为 true 就等价于给元素增加 inert 状态,设为 false 则移除这个元素自身的显式 inert 状态。下面的示例还保存了打开前的焦点,关闭后把焦点还给触发按钮。
const pageShell = document.querySelector('#page-shell')
const modal = document.querySelector('#edit-modal')
const openButton = document.querySelector('#open-modal')
const closeButton = document.querySelector('#close-modal')
let lastFocusedElement = null
function openModal() {
// 记录触发控件,关闭时把键盘焦点还给它。
lastFocusedElement = document.activeElement
pageShell.inert = true
modal.hidden = false
// 等弹窗显示后再聚焦内部控件,避免 hidden 状态拦截 focus。
closeButton.focus()
}
function closeModal() {
// 先移除背景的 inert 状态,再隐藏弹窗。
pageShell.inert = false
modal.hidden = true
// 只有仍在当前文档中的元素才适合恢复焦点。
if (lastFocusedElement instanceof HTMLElement && lastFocusedElement.isConnected) {
lastFocusedElement.focus()
}
}
openButton.addEventListener('click', openModal)
closeButton.addEventListener('click', closeModal)
这段代码只解决“背景是否能交互”和“打开前焦点如何回来”两个问题。若要实现完整的焦点循环、Escape 关闭和滚动锁定,还要根据模态框组件的实际需求继续设计。
dialog.showModal() 与手动 inert 有什么区别
原生 通过 showModal() 进入模态状态时,对话框外的文档内容会自动变成 inert;这适合愿意采用原生对话框语义的页面。自定义 div 弹窗不会自动获得这个行为,必须手动切换背景容器。
const dialog = document.querySelector('#profile-dialog')
const openDialog = document.querySelector('#open-dialog')
const closeDialog = document.querySelector('#close-dialog')
openDialog.addEventListener('click', () => {
// showModal() 进入原生模态状态,外部文档会被浏览器隔离。
dialog.showModal()
})
closeDialog.addEventListener('click', () => {
// close() 退出模态状态,浏览器恢复外部文档的交互。
dialog.close()
})
要注意两个边界:第一,显式给对话框自身加 inert 会让它也不能操作;第二,父元素继承的 inert 状态不能靠子元素设置 inert = false 抵消。需要解除时,应从真正带有 inert 的祖先节点开始恢复。

给 inert 状态补上可见提示
inert 本身不会自动改变颜色或透明度。若背景内容被禁止操作却仍然看起来完全正常,用户可能不知道为什么按钮暂时不能用。可以用属性选择器补充视觉提示,但不要把视觉样式当作 inert 的替代品。
/* 只提示被 inert 的背景区域,交互限制仍由 inert 属性负责。 */
[inert] {
opacity: 0.55;
filter: saturate(0.7);
}
/* 弹窗打开时禁止背景滚动,避免视觉焦点和页面位置脱节。 */
body:has(#edit-modal:not([hidden])) {
overflow: hidden;
}
如果浏览器兼容目标不支持 :has(),可以在打开和关闭时给 body 增删一个 class。视觉提示、滚动处理和 inert 的职责要分开,便于后续更换组件。
disabled、aria-hidden 与 inert 不能互相替代
| 手段 | 主要作用 | 适用边界 |
|---|---|---|
inert | 冻结元素及后代的交互、聚焦和辅助技术访问 | 整块背景、暂时不可操作的区域 |
disabled | 禁用单个表单控件 | 按钮、输入框等控件自身不可用 |
aria-hidden | 改变辅助技术的语义可见性 | 不能单独阻止真实点击或键盘聚焦 |
| 遮罩 CSS | 表达层级、暗化背景和视觉状态 | 不能单独完成交互隔离 |
常见错误是只写 aria-hidden="true",却留下可聚焦的链接和按钮;或者只把背景盖住,却没有把键盘焦点移进弹窗。实践中通常是 inert + 明确焦点管理 + 视觉提示 组合使用。
一份收尾清单
- 自定义弹窗先保证背景有统一根节点,再切换
HTMLElement.inert。 - 打开时保存触发元素,关闭时确认它仍在文档中再恢复焦点。
- 原生
dialog.showModal()已经提供模态外部隔离,不要重复给错误的父节点加 inert。 - 不要用
aria-hidden代替真实的交互禁用,也不要用透明度代替 inert。 - 父级继承的 inert 不能由子级简单设置为 false,恢复状态时要回到实际控制节点。
一句话总结:遮罩解决“看起来被挡住”,inert 解决“确实不能交互”,而焦点管理解决“用户接下来从哪里继续操作”。把三者拆开设计,模态框的键盘和无障碍行为会更稳定。
相关问题
给一个按钮设置 inert 可以代替 disabled 吗?
不建议。单个表单控件的语义状态优先使用 disabled;inert 更适合冻结一整块内容及其后代。
inert 会自动显示灰色或半透明效果吗?
不会。它主要改变交互和可访问性状态,视觉变化要由页面自己的 CSS 明确表达。
dialog.showModal() 还需要手动给背景加 inert 吗?
正常原生模态对话框不需要再手动冻结整个文档;只有自定义弹窗、特殊嵌套结构或额外的业务区域才需要单独设计。
Linux systemd-analyze dump 怎样按 unit 过滤服务管理器状态
- 上一篇
- Linux systemd-analyze dump 怎样按 unit 过滤服务管理器状态
- 下一篇
- JavaScript Element.toggleAttribute 怎样同步布尔属性
-
- 文章 · 前端 | 45分钟前 | 前端 · CSS Ruby ruby-align rt 注音排版
- CSS ruby-align 怎样调整注音与汉字的对齐方式
- 124浏览 收藏
-
- 文章 · 前端 | 46分钟前 |
- ElementInternals 怎样让自定义元素参与表单校验
- 109浏览 收藏
-
- 文章 · 前端 | 49分钟前 |
- Service Worker Cache 怎样按请求方法过滤缓存
- 166浏览 收藏
-
- 文章 · 前端 | 50分钟前 | javascript · css · range CSS Custom Highlight API Highlight CSS.highlights ::highlight()
- CSS Custom Highlight API 怎样高亮搜索结果而不改 DOM
- 118浏览 收藏
-
- 文章 · 前端 | 55分钟前 | 前端 · CSS container-type @container scroll-state 滚动状态查询
- CSS scroll-state() 怎样根据容器滚动状态切换样式
- 441浏览 收藏
-
- 文章 · 前端 | 58分钟前 | 错误处理 · javascript · 异步编程 · 前端开发 · JavaScript 异步任务 Promise Promise.allSettled 结果处理
- JavaScript Promise.allSettled 怎样保留每个任务结果
- 410浏览 收藏
-
- 文章 · 前端 | 1小时前 | css · 瀑布流布局 Grid @supports CSS Masonry CSS grid lanes 不等高卡片
- CSS grid lanes 怎样实现不等高卡片的紧凑布局
- 486浏览 收藏
-
- 文章 · 前端 | 1小时前 | css · anchor-name position-area CSS anchor positioning
- CSS anchor positioning 怎样把提示框对齐到按钮
- 344浏览 收藏
-
- 文章 · 前端 | 1小时前 | javascript · 前端开发 · 浏览器API · JavaScript sort 浅拷贝 toSorted Array.prototype.toSorted 不可变排序
- JavaScript Array.toSorted 怎样避免原数组被改写
- 177浏览 收藏
-
- 文章 · 前端 | 1小时前 |
- JavaScript Map.groupBy 怎样按对象引用分组
- 106浏览 收藏
-
- 文章 · 前端 | 1小时前 | javascript · 浏览器API · JavaScript dom Hidden disabled 布尔属性 Element.toggleAttribute
- JavaScript Element.toggleAttribute 怎样同步布尔属性
- 102浏览 收藏
-
- 文章 · 前端 | 23小时前 | vite package.json optimizeDeps 依赖预构建 条件导出
- Vite 依赖预构建为什么会因条件导出重复
- 357浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 857次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 862次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 938次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 919次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 747次使用
-
- 移动端输入框聚焦后按钮被键盘挡住怎么办:用 visualViewport 做底部适配
- 2026-06-29 424浏览
-
- golang解析html网页的方法
- 2022-12-29 132浏览
-
- Go text/template与html/template选择输出边界的对比
- 2026-09-23 275浏览
-
- Go Goja 怎么预编译脚本并在多个运行时执行
- 2026-10-13 306浏览
-
- Go html/template 怎样区分文本和 HTML 内容
- 2026-10-14 281浏览
