You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 15:34:52