Logo

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:

Date picker appears behind HTML dialog

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:

Date picker nowhere to be seen

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:

Date picker overflowing dialog container

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:

Date picker show in front of Bootstrap modal

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.


Email me if you have any questions about this post.

Subscribe to the RSS feed to keep updated.