showModal() 将 dialog 推入浏览器顶层栈并自动生成 ::backdrop,不受 CSS z-index 和父容器堆叠上下文影响;show() 仅设 open 属性,dialog 仍受文档流约束且不生成 ::backdrop。

showModal() 会把 dialog 推入浏览器顶层栈,show() 不会
两者都让 dialog 可见,但 DOM 层级行为完全不同:showModal() 触发浏览器原生“顶层层叠协议”,将该元素插入 top layer(类似 fullscreen 或 alert()),绕过所有 CSS z-index 控制;而 show() 只是设 open 属性,它仍受普通文档流和父容器堆叠上下文约束。
这意味着:
-
showModal()的dialog和::backdrop总在最上层,哪怕父元素有transform、position: fixed或overflow: hidden,也不会被裁剪(但 backdrop 渲染可能受影响) -
show()的dialog如果嵌套在transform容器里,它的定位和 backdrop 显示会出问题——甚至完全不可见 - 多个
showModal()调用按顺序形成视觉栈(后调用的盖在前一个上面),但 DOM 中它们仍是平级兄弟节点,不改变 HTML 结构顺序
showModal() 自动生成 ::backdrop 并参与层叠,show() 完全不生成
::backdrop 是浏览器为 showModal() 自动创建的伪元素,它不是子节点,也不在 DOM 树中,但它有自己的渲染层——且必须显式写 CSS 才可见:
dialog::backdrop {
background: rgba(0, 0, 0, 0.5);
}
而 show() 根本不触发 ::backdrop 创建,所以无论你怎么写 dialog::backdrop 都无效。这也意味着:
立即学习“前端免费学习笔记(深入)”;
- 点击遮罩关闭只对
showModal()生效(前提是没禁用pointer-events) -
show()下的dialog点击穿透,背景仍可滚动、聚焦、交互 - Firefox 当前只做逻辑阻塞(无 backdrop 渲染),Chrome/Edge 111+ 和 Safari 17.4+ 支持渲染,但样式必须手动补全
父容器 transform 或 overflow: hidden 会截断 show(),但对 showModal() 影响有限
如果你把 dialog 放在带 transform 或 overflow: hidden 的 div 里:
-
show():dialog 会被裁剪,定位失常,backdrop 完全不出现(因为它本来就不生成) -
showModal():dialog 本身仍能正确居中显示(因 top layer 脱离文档流),但::backdrop可能被父容器裁掉——尤其当父容器是transform触发的新 stacking context 时 - 最佳实践是把
dialog直接挂到document.body下,避免嵌套在任何影响堆叠上下文的容器中
DOM 就绪状态对两者调用失败的影响不同
调用失败时,错误表现和原因有差异:
-
showModal()报DOMException: The element does not have a namespace→ 多半是脚本执行太早,DOMContentLoaded前就调用了 -
showModal()报DOMException: The element is already open→ 忘了检查modal.open,重复调用 -
show()在旧版 Safari(15.6 之前)直接报TypeError: dialog.show is not a function,因为该方法未实现 - 两者都要求元素已挂载到主文档流;若
dialog在 Shadow DOM 内,showModal()会抛DOMException: The element is not in a top layer,show()则可能静默失败或样式错乱



















