如何在Bootstrap 5.2+版本中打开多个不关闭旧弹窗的模态框?
Bootstrap 5.2+ 多模态框叠加显示解决方案
问题说明
从Bootstrap 3升级至5.2及更高版本后,原支持的多模态框叠加功能失效:打开新模态框时,已打开的旧模态框会自动关闭。而Bootstrap 3及5.0-5.1版本中,新模态框可正常覆盖旧模态框实现叠加效果,且项目必须使用5.2+版本。
解决思路
Bootstrap 5.2起,模态框组件默认添加了「打开新模态框时关闭所有其他模态框」的逻辑。我们需要通过监听事件阻止该默认行为,并手动调整模态框层级以保证叠加显示的视觉效果。
具体实现
1. 核心修复代码
在页面中添加以下JavaScript代码,覆盖默认的模态框行为:
// 监听所有模态框的show事件,阻止关闭其他模态框的默认行为 document.addEventListener('show.bs.modal', function (e) { // 移除默认生成的全局遮罩层 const backdrop = document.querySelector('.modal-backdrop'); if (backdrop) { backdrop.remove(); } // 计算当前已打开模态框的最高层级,为新模态框设置更高层级 const modals = document.querySelectorAll('.modal.show'); const newModal = e.target; let highestZIndex = 1050; // Bootstrap默认模态框z-index起始值 modals.forEach(modal => { const currentZIndex = parseInt(window.getComputedStyle(modal).zIndex); if (currentZIndex > highestZIndex) { highestZIndex = currentZIndex; } }); // 设置新模态框和对应遮罩层的层级 newModal.style.zIndex = highestZIndex + 20; const newBackdrop = document.createElement('div'); newBackdrop.className = 'modal-backdrop fade show'; newBackdrop.style.zIndex = highestZIndex + 10; document.body.appendChild(newBackdrop); // 记录当前模态框的遮罩层级,用于关闭时匹配移除 newModal._backdropZIndex = highestZIndex + 10; }); // 监听模态框关闭事件,移除对应遮罩层并恢复页面状态 document.addEventListener('hide.bs.modal', function (e) { const modal = e.target; // 移除当前模态框对应的遮罩层 const backdrops = document.querySelectorAll('.modal-backdrop'); backdrops.forEach(backdrop => { if (parseInt(backdrop.style.zIndex) === modal._backdropZIndex) { backdrop.remove(); } }); // 若已无打开的模态框,恢复body默认样式 const remainingModals = document.querySelectorAll('.modal.show'); if (remainingModals.length === 0) { document.body.classList.remove('modal-open'); document.body.style.paddingRight = ''; } });
2. 完整示例代码
<head> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous"> </head> <body class="p-4"> <a data-bs-toggle="modal" href="#myModal" class="btn btn-primary">Launch modal</a> <div class="modal" id="myModal" aria-hidden="true"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title">Modal title</h4> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button> </div> <div class="modal-body"> Content for the dialog / modal goes here. <a data-bs-toggle="modal" href="#myModal2" class="btn btn-primary">Launch modal</a> </div> <div class="modal-footer"> <a href="#" data-bs-dismiss="modal" class="btn btn-outline-dark">Close</a> </div> </div> </div> </div> <div class="modal" id="myModal2" data-bs-backdrop="static" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title">2nd Modal title</h4> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button> </div> <div class="modal-body"> Content for the dialog / modal goes here. Content for the dialog / modal goes here. Content for the dialog / modal goes here. Content for the dialog / modal goes here. Content for the dialog / modal goes here. </div> <div class="modal-footer"> <a href="#" data-bs-dismiss="modal" class="btn btn-outline-dark">Close</a> <a href="#" class="btn btn-primary">Save changes</a> </div> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script> <script> // 核心修复代码 document.addEventListener('show.bs.modal', function (e) { const backdrop = document.querySelector('.modal-backdrop'); if (backdrop) { backdrop.remove(); } const modals = document.querySelectorAll('.modal.show'); const newModal = e.target; let highestZIndex = 1050; modals.forEach(modal => { const currentZIndex = parseInt(window.getComputedStyle(modal).zIndex); if (currentZIndex > highestZIndex) { highestZIndex = currentZIndex; } }); newModal.style.zIndex = highestZIndex + 20; const newBackdrop = document.createElement('div'); newBackdrop.className = 'modal-backdrop fade show'; newBackdrop.style.zIndex = highestZIndex + 10; document.body.appendChild(newBackdrop); newModal._backdropZIndex = highestZIndex + 10; }); document.addEventListener('hide.bs.modal', function (e) { const modal = e.target; const backdrops = document.querySelectorAll('.modal-backdrop'); backdrops.forEach(backdrop => { if (parseInt(backdrop.style.zIndex) === modal._backdropZIndex) { backdrop.remove(); } }); const remainingModals = document.querySelectorAll('.modal.show'); if (remainingModals.length === 0) { document.body.classList.remove('modal-open'); document.body.style.paddingRight = ''; } }); </script> </body>
效果说明
- 打开新模态框时,旧模态框不会关闭,新模态框将覆盖在旧模态框上方
- 关闭上层模态框后,下层模态框可正常继续操作
- 遮罩层会随对应模态框的关闭而移除,避免多层遮罩导致页面过暗
内容的提问来源于stack exchange,提问作者andre.hey
相关产品推荐
相关产品推荐

