根本原因是dialog未调用showModal()或调用失败:必须是body直接子元素、DOM就绪后执行、父容器无transform/overflow:hidden;::backdrop仅支持background等有限样式;点击遮罩需手动监听;关闭必须用close()。

dialog 标签不遮挡底部元素,根本原因不是 CSS 层级没调高,而是它压根没“启动”模态行为——showModal() 没被调用,或调用了但执行失败。
为什么 dialog 看起来像没遮罩?
常见现象:弹窗内容出来了,但底下按钮还能点、滚动条能动、Tab 键照常切换到页脚。这不是样式问题,是语义没激活。
-
<dialog open>或dialog.open = true只让内容“可见”,不生成::backdrop,也不锁交互 -
dialog.show()同样无效:无遮罩、无焦点围栏、Esc 不响应 - 浏览器 DevTools 里查不到
::backdrop节点?说明showModal()根本没走通
showModal() 调用失败的三大硬性条件
即使写了 dialog.showModal(),也可能静默失败。必须逐项核对:
-
<dialog>必须是<body>的直接子元素——嵌套在<div id="app">或<main>里,Safari 和部分 Chrome 会丢掉 backdrop 层 - 脚本必须在 DOM 就绪后执行:
DOMContentLoaded事件内,或把<script>放在</body>前;否则document.querySelector('dialog')返回null - 父容器不能有
transform、will-change或overflow: hidden——这些会干扰dialog的定位与 backdrop 渲染,导致遮罩偏移、裁剪甚至完全不可见
dialog::backdrop 样式写对了但没生效?
伪元素失效,90% 是因为选择器或上下文错位:
立即学习“前端免费学习笔记(深入)”;
- 必须用
dialog::backdrop,不能省略dialog前缀(::backdrop或.modal::backdrop全部无效) - 只支持有限属性:
background(推荐rgba(0,0,0,0.6))、opacity、backdrop-filter;z-index、margin、padding会被忽略 - 旧版 Safari(≤15.6)不支持
::backdrop,需降级:用dialog-polyfill或 JS 手动插入遮罩<div class="backdrop"></div>
点击遮罩不关闭?这不是 bug,是规范没定义
原生 dialog 不提供“点击 backdrop 关闭”功能,必须手动监听并判断点击区域:
- 监听
dialog元素的click事件,检查event.target === dialogEl(注意:Safari 中该判断不可靠,建议加容错) - 避免在内部按钮或表单上写
event.stopPropagation(),否则 click 无法冒泡上来 - 移动端要额外加
touch-action: auto到dialog::backdrop,否则 iOS Safari 可能穿透点击
最易被忽略的一点:关闭必须用 dialog.close(),而不是删 open 属性或设 open = false——后者会导致 backdrop 残留、close 事件不触发、后续 showModal() 失效。



















