Why the HTML dialog element sucks
Learn why you should implement custom modals instead of relying on dialog
Published: 04 Feb, 2025
The HTML dialog element gets a lot of praise for providing a way to show modals without having to write custom Javascript, or CSS, because it’s built into the browser. I was happy with them as a lightweight alternative to Bootstrap modals until I discovered a deal breaking quirk that I’m going to share with you today.
No z-index
Dialog elements are appended to the root of DOM with a separate stacking context. This means that you have zero control over what can appear in front of the dialog.
See this example:
Here, I have a dialog with input elements that will display a date picker when clicked. However, the date picker can’t appear in front of the dialog because of the different stacking context that takes precedence over everything else.
Working around
To “solve” this problem, you can configure the date picker to be a child of the dialog element instead of the body, which what it does by default. This will cause the date picker to display inside the dialog, in the same stacking context.
Now look at what happens:
Notice the vertical and horizontal scroll bars. It means that the date picker is positioned in an undesirable place, which is the bottom right corner, where you can’t see it without scrolling.
To solve this problem, you can configure the date picker to be positioned static, relative to the input element.
Look at the result:
Now it seems to be working, but the date picker is overflowing because the dialog element’s height isn’t large enough to accomodate the picker. You’ll have to scroll to see the entire thing, or write custom Javascript to dynamically adjust the dialog’s height when the picker is open. Quite annoying.
Bootstrap modal
Take a look at how it works with Bootstrap modals:
The picker displays in front of the modal because Bootstrap modals are children of the document’s body, just like the picker is by default. This means that you can use z-index to show any element in front of a modal, unlike dialogs.
Conclusion
As you saw, using the HTML dialog element is too annoying to use because of the inability to play with z-index to display other elements on top.
This might not be a big deal for simple use cases, but if you’re building modals with complex interactions, it’s best if you spend some time building a custom modal component, or use one from a library like Bootstrap instead of relying on the dialog element.