Multiple Bootstrap Modals: From z-index Wars to Native Dialogs
From a 2015 Stack Overflow question about stacking Bootstrap modals with z-index hacks to the native <dialog> element and top-layer API in 2026.
Multiple Bootstrap Modals: From z-index Wars to Native Dialogs
Back in 2015, I asked a question on Stack Overflow in Portuguese about stacking multiple Bootstrap modals. The problem was painfully common: you open a modal, then need to open another modal on top of it — maybe a confirmation dialog or a detail view. Bootstrap wasn’t designed for that. The question got 13 upvotes because every Bootstrap developer ran into this wall eventually.
The workarounds were ugly, and the fact that we needed them at all says a lot about how far the platform has come.
The 2015 Problem: z-index Chaos
Bootstrap modals use a fixed z-index value for both the modal itself and its backdrop overlay. When you opened a second modal, it would render behind the first modal’s backdrop, making it unclickable. The backdrop stacking was completely broken.
The “solutions” floating around at the time were all hacks:
// Manually increment z-index for each new modal
$(document).on('show.bs.modal', '.modal', function () {
var zIndex = 1040 + 10 * $('.modal:visible').length;
$(this).css('z-index', zIndex);
setTimeout(function () {
$('.modal-backdrop')
.not('.modal-stacked')
.css('z-index', zIndex - 1)
.addClass('modal-stacked');
}, 0);
});
You’d listen for modals opening, count how many were visible, and manually bump the z-index of both the modal and its backdrop. Some solutions went further — adjusting body padding, managing scroll locks, handling the hidden.bs.modal event to restore previous modal states.
It was fragile. Every edge case — closing the top modal, pressing Escape, clicking the backdrop — needed special handling. And if you got the z-index math wrong, you’d end up with a backdrop covering everything and no way to interact with the page.
Why It Was Hard
The fundamental issue was that CSS z-index creates stacking contexts, and those contexts are relative to parent elements. There was no concept of “put this element above everything else on the page, guaranteed.” You had to manually manage a global z-index hierarchy, and every library on the page might be competing for the same z-index ranges.
Bootstrap’s modal was also tightly coupled to jQuery, the DOM, and a single-backdrop assumption. The architecture simply didn’t support stacking.
What Changed: Native <dialog> and Top Layer
HTML now has the <dialog> element, and when you call showModal(), the browser places it in something called the top layer. The top layer sits above everything in the document — above all z-index stacking contexts, above all other elements. Period.
<dialog id="confirm">
<h2>Are you sure?</h2>
<button onclick="this.closest('dialog').close()">Yes</button>
</dialog>
<script>
document.getElementById('confirm').showModal();
</script>
Multiple dialogs opened with showModal() stack naturally. Each one goes into the top layer in order. The browser manages the stacking, the focus trapping, and the backdrop. No z-index math. No JavaScript hacks.
The ::backdrop pseudo-element gives you full styling control:
dialog::backdrop {
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(4px);
}
Each dialog gets its own backdrop, properly stacked. You can style them differently, animate them, and the browser handles the ordering.
Focus Management for Free
When a <dialog> opens via showModal(), the browser traps focus inside it. Tab and Shift+Tab cycle through the dialog’s focusable elements. When the dialog closes, focus returns to the element that opened it. In 2015, we wrote dozens of lines of JavaScript to approximate this behavior — and usually got edge cases wrong.
Escape Key, Click Outside
Pressing Escape closes the topmost dialog. You can listen for the close event to clean up. Clicking the backdrop can be handled with a simple pattern — checking if the click target is the dialog element itself (not its children).
The Lesson
We spent years building JavaScript workarounds for what turned out to be a missing platform primitive. The <dialog> element with showModal() and the top layer API solved modal stacking, focus trapping, backdrop management, and accessibility in one shot.
If you’re still using Bootstrap modals in 2026, you’re fighting a battle the browser already won. The native <dialog> does less — no animations out of the box, no fancy transitions — but the foundation is solid. Layer your own CSS on top, and you’ll never count z-index values again.
Related Posts
Multiple Bootstrap Modals: From z-index Wars to Native Dialogs
From a 2015 Stack Overflow question about stacking Bootstrap modals with z-index hacks to the native <dialog> element and top-layer API in 2026.
Add to Favorites: From Browser APIs to PWA Install
My 2015 SO answer showed window.external.AddFavorite() for IE. In 2026, browsers removed programmatic bookmarking entirely — but PWA Install replaced it.
Bootstrap Modal + Tooltip: From jQuery Plugin Wars to Native HTML
My 2015 Stack Overflow answer tackled Bootstrap modal and tooltip conflicts on the same element. In 2026, native dialog and popover make Bootstrap optional.