I found a slightly different approach to the most voted one, although concept is quite similar. I will use my sidebars code as example.
In HTML I have stuff like this:
<dialog class="sidebar modal">
<aside>
</aside>
</dialog>
In CSS I have this:
/*Need this to reset padding, which is 1rem by default, so that dialog's content "covers" the whole element.*/
dialog {
padding: 0;
}
/*Styling of child element, in my case I have `aside`*/
.sidebar aside {
/*This can vary, but the point is to make sure that whatever child you have at covers completely matches the size of the dialog element.*/
display: flex;
flex-direction: column;
justify-content: center;
height: inherit;
/*If you want to have some spacing around the main actual dialog content use padding, not margin, because if you click on the margin of the element, it will be considering clicking on the element "under" it, but padding will be treated as part of the element you are clicking on. In fact, depending on the above styling or other child elements, you may even need to use this.*/
padding: 1rem;
}
Then in my JS code I have this:
//Handle dialog closure when clicking outside dialog content
const dialogs = document.querySelectorAll('dialog');
if (!empty(dialogs)) {
dialogs.forEach((dialog) => {
dialogInit(dialog);
});
}
function dialogInit(dialog)
{
//For my needs I check for class `modal`, but you can use any other class or do this for all dialog elements, if you know that all of them will be modal
if (dialog.classList.contains('modal')) {
dialog.addEventListener('click', (event) => {
//If we setup styling correctly, clicking "outside" of the dialog means clicking on its margin. Since it is margin, event target is actually an element under the dialog element, which is its backdrop, which is a pseudo element, and thus it is still treated as clicking on dialog.
if (event.target && event.target === dialog) {
dialog.close();
}
});
}
}
Again, the concept is practically same, but in reverse, and I think it may make it a bit more universal, because you are not limited to what type of child element you have in the dialog, as long as you set its size correctly.