A Simple Script for HTML <dialog>s

A quick & simple script that makes it easy to open HTML dialog elements based on a data attribute. Add the script, add the target as data and you're good to go!

I've been messing around with the HTML dialog element now that browser support is so great, and I think it's awesome! The part that's not ideal is that you need JavaScript to open a dialog, even though you can get away without it to close them.

As such, I've put together a quick script that allows you to easily add click event listeners to elements that open a dialog specific by a data attribute.The basic idea is you can add a button on a page, slap on the attribute, and then you've got a whole dialog/modal ready to rock and roll. The buttons below are examples that open 2 different modals.

Here's the JavaScript that does it:

    
const modalOpeners = document.querySelectorAll('[data-modal]');

modalOpeners.forEach((n) => {
    const m = document.querySelector(`#${n.getAttribute('data-modal')}`);
    n.addEventListener('click', () => {
        m.showModal();
        m.classList.add('opening');
        document.body.style.overflowY = 'hidden'; // prevent document scrolling in background
    })

    function close() {
        m.classList.remove('opening');
        m.classList.add('closing');

        setTimeout(() => {
            m.classList.remove('closing');
            m.close();
            document.body.style.overflowY = 'unset';
        }, 300);
    }

    m.querySelector('.closer').addEventListener('click', close);
    m.addEventListener('cancel', close);
})

And here's a quick reference for the HTML to go with it:

    
    <button class="btn" data-modal="modal-one">Open Modal 1</button>

    <dialog id="modal-one">
        <div class="modal-content">
            <h2>This is Modal One!</h2>
            <p>I hope you enjoyed the content experience inside Modal One! You can close the modal with the close modal button.</p>
            <button class="btn closer">Close Modal</button>
        </div>
    </dialog>

The final piece of the puzzle is the CSS that handles the display of things and provides the smooth transitions:

    
dialog::backdrop {
    background: unset;
    transition: all 0.3s;
}

dialog[open]::backdrop {
    backdrop-filter: blur(3px) brightness(0.46);
}

dialog {
    all: unset;
    position: fixed;
    z-index: -420;
    inset: 0;
    margin: 0;
    padding: 0;
    border: none;
    display: none;
    place-items: center;
}

dialog[open],
dialog.closing {
    z-index: 69469;
    display: grid;
}

dialog[open].closing::backdrop {
    backdrop-filter: none;
}

dialog>div {
    opacity: 0;
    transform: translateY(50px);
    transition: all 0.3s cubic-bezier(0.39, 0.575, 0.565, 1);
    max-height: 90vh;
    overflow: scroll;
}

dialog.opening>div {
    opacity: 1;
    transform: translateY(0px);
}

dialog.closing>div {
    opacity: 0;
    transform: translateY(100px);
}

This is Modal One!

wooden barrel with organic cider sign

I hope you enjoyed the content experience inside Modal One! You can close the modal with the close modal button.

wooden barrel with organic cider sign

This is Modal Two!

I hope you enjoyed the content experience inside Modal Two! You can close the modal with the close modal button.