Bootstrap最新不支持多层Modal,因其单例设计导致z-index固定(.modal为1055、.modal-backdrop为1050)、遮罩错位、焦点失控;临时方案是监听show.bs.modal动态提升z-index并同步调整.backdrop,但推荐改用折叠面板、选项卡等更健壮的交互替代。
Bootstrap 最新不支持多层 Modal,强行弹出多个会导致 .modal 和 .modal-backdrop 的 z-index 错位、遮罩错位、焦点丢失,这不是配置问题,而是设计限制。
根本原因是 Bootstrap 5 默认只维护一套层级:所有 .modal 共享 z-index: 1055,.modal-backdrop 固定为 1050,且 DOM 中只保留一个 backdrop 元素。后打开的 Modal 没有自动提升层级,就必然被压在下面。
z-index 还是 1055
$('.modal:visible').length 在 show.bs.modal 阶段可能不准,因为动画尚未开始,DOM 可见性未更新.modal.in 判断——Bootstrap 5 已弃用 .in 类,应改用 :visible 或 data('bs.modal')?.isShown
不改源码、不引入第三方插件,仅靠原生 Bootstrap 5 + jQuery 即可临时支撑 2 层嵌套(如主表单 + 删除确认):
show.bs.modal,用 setTimeout(() => {}, 0) 确保获取到准确的可见 Modal 数量z-index:例如 1055 + (10 * visibleCount)
$('.modal-backdrop').last()(不是 .first()),设为 zIndex - 1
$(document).on('show.bs.modal', '.modal', function() {setTimeout(() => {const visibleModals = $('.modal:visible').length;const newZIndex = 1055 + (10 * visibleModals);$(this).css('z-index', newZIndex);$('.modal-backdrop').last().css('z-index', newZIndex - 1);}, 0);});
不是 z-index 数值写小了,而是它们和 Modal 分属不同层叠上下文(stacking context):
transform: translateZ(0)、opacity: 0.99、position: relative(没配 z-index)都会隐式创建新层叠上下文.modal 是 document.body 直系子节点,但 Tippy 默认挂载到触发元素附近,天然隔离$zindex-modal 默认是 1050,Tippy.js 默认用 2147483647,硬覆盖 z-index: 9999 !important 会破坏下拉菜单($zindex-dropdown: 1000)等其他组件.modal .tippy-box { z-index: calc(#{$zindex-modal} + 5) !important; }
真正难的不是算 z-index,而是确保所有弹层共享同一层叠上下文——这要求 DOM 挂载位置一致、触发新上下文的 CSS 属性被显式收敛、变量体系对齐。多数“必须多层 Modal”的需求,其实该用折叠面板、选项卡或向导组件替代。