HTML 原生 dialog 完整教学:不用插件也能做出专业 Modal
快速解答
用 dialog 标签包住内容,搭配 JavaScript 的 showModal() 开启、close() 关闭。不需要任何插件,浏览器全面支持,还内建无障碍功能和 ::backdrop 遮罩。
还在自己写 Modal?浏览器早就帮你做好了
以前要做一个 Modal,需要:
- 自己写一层
.overlaydiv 遮住背景 - 用 JavaScript 切换
display: none / block - 手动锁定背景滚动
- 自己监听 Esc 键关闭
- 还要处理无障碍(focus trap、aria 属性)
现在呢?HTML 原生 <dialog> 帮你全部搞定,一个标签解决所有问题。
浏览器支持率已超过 96%,Chrome、Firefox、Safari、Edge 全面支持,可以放心用在正式项目。
基本语法:开启与关闭
<dialog> 的核心很简单,只要记住两个 JavaScript 方法:
<dialog id="my-modal">
<p>这是 Modal 的内容</p>
<button id="close-btn">关闭</button>
</dialog>
<button id="open-btn">开启 Modal</button>const modal = document.getElementById('my-modal');
document.getElementById('open-btn').addEventListener('click', () => {
modal.showModal(); // 开启 Modal(带背景遮罩)
});
document.getElementById('close-btn').addEventListener('click', () => {
modal.close(); // 关闭 Modal
});showModal() vs show() 的差异
| 方法 | 效果 |
|---|---|
showModal() | 全屏 Modal,产生 ::backdrop 遮罩,自动锁定焦点,Esc 键可关闭 |
show() | 非阻断弹窗,无遮罩,不锁定焦点 |
一般做 Modal 用 showModal(),工具提示或浮动面板用 show()。
基本 Modal 开关示范
::backdrop:自定义背景遮罩
showModal() 开启时,浏览器会自动产生一个 ::backdrop 伪元素盖在 Modal 后方。你可以直接用 CSS 改它的外观:
dialog::backdrop {
background: rgba(0, 0, 50, 0.6);
backdrop-filter: blur(8px);
}以前要做毛玻璃背景遮罩,需要自己叠很多层 div;现在一行 CSS 就搞定。
自定义 ::backdrop 毛玻璃效果
表单整合:method='dialog'
这是 <dialog> 最强的隐藏功能之一:把 <form> 的 method 设为 "dialog",提交表单时会自动关闭 dialog 并记录按下的按钮值,确认/取消逻辑完全不需要自己写。
<dialog id="confirm-modal">
<p>确定要删除这笔数据吗?</p>
<form method="dialog">
<button value="cancel">取消</button>
<button value="confirm">确定删除</button>
</form>
</dialog>modal.addEventListener('close', () => {
// returnValue 是被点击按钮的 value
if (modal.returnValue === 'confirm') {
// 执行删除逻辑
}
});confirm 确认对话框
进场动画:@starting-style
<dialog> 默认没有开启动画,但搭配 CSS 的 @starting-style,可以做出纯 CSS 的进场动画,不需要 JavaScript 切换 class。
dialog[open] {
opacity: 1;
transform: translateY(0);
transition: opacity 0.3s ease, transform 0.3s ease;
}
@starting-style {
dialog[open] {
opacity: 0;
transform: translateY(-16px);
}
}@starting-style 定义的是元素刚出现时的初始值,transition 接着把它带到 dialog[open] 的样式,产生平滑进场。这个方法不需要任何 JavaScript,纯 CSS 搞定。
支持度:Chrome 117+、Firefox 129+、Safari 17.5+,涵盖超过 90% 的用户。
带进场动画的完整 Modal
注意开启时的滑入动画
常见问题
Q:点击背景遮罩可以关闭吗?
原生 <dialog> 不支持点击背景关闭,需要自己加:
modal.addEventListener('click', (e) => {
if (e.target === modal) modal.close();
});Q:可以阻止 Esc 键关闭吗?
modal.addEventListener('cancel', (e) => {
e.preventDefault();
});Q:跟 Bootstrap modal 比有什么缺点?
- 关闭动画需要额外处理(
@starting-style目前只支持进场) - 没有内建的「点击背景关闭」行为
- 旧项目迁移有一定成本
不过新项目的话,原生 <dialog> 无需插件、天生无障碍、性能更好,完全值得优先选用。
总结:值得换掉旧写法吗?
如果你还在用这些方式做 Modal:
- Bootstrap modal
- 自己用 div 叠出来的 overlay
- jQuery UI dialog
是时候换了。<dialog> 的优势很明确:
- 无障碍免费送:自动管理 focus trap、aria 属性
- Esc 键内建:不需要自己监听
- 背景锁定:
showModal()自动阻止背景滚动 - ::backdrop:遮罩样式一行 CSS
- 零依赖:不需要任何插件
对新项目来说,<dialog> 应该是默认选择。Bootstrap modal 留给需要向下兼容的旧项目就好。