For years if you wanted to make a modal dialog
box you'd have to make a div, hide it and then display it when the user did a certain action. This was easy to throw together but accessibility wasn't great, a common error was leaving elements of the dialog
in the tab index meaning a user would have to tab through every element of the dialog
before they could move on.
As you've probably worked out I'll be writing about the native dialog
element and how I use it. At the time of writing, support is, unsurprisingly, not all that great.
The dialog
element
I always like to take a dive into Mozilla's dev site to help learn about new elements so here is how they describe it.
The HTML
<dialog>
element represents a dialog box or other interactive component, such as an inspector or window.
OK, but what does that mean? The syntax looks simple enough so let's give it a go.
<dialog open> Test dialog </dialog>
How it looks in a supported browser.
And there we have it, thanks for read... Oh, we're not quite done yet. We need to interact with the dialog
, having it there all the time really isn't that helpful. Mozilla gives us a usage example but no information to go with it, so let's look elsewhere.
The w3 spec
When in doubt head to the spec and sure enough we have 3 functions for interacting with the dialog
and they each have descriptions.
dialog . show( [
anchor
] )
Displays the dialog element.
The argument, if provided, provides an anchor point to which the element will be fixed.dialog . showModal( [
anchor
] )
Displays the dialog element and makes it the top-most modal dialog.
The argument, if provided, provides an anchor point to which the element will be fixed.
This method honors the autofocus attribute.dialog . close( [
result
] )
Closes the dialog element.
The argument, if provided, provides a return value.
Putting this in practice
Now, this is my own way of putting this into practice if you think it shouldn't be done this way let me know.
With label
s you have a for
attribute that lets you point to an element, by ID, that you want the label to be connected with. This inspired me to have a data-modal-for
, data because it's not a real attribute.
<button data-modal-for="testDialog" open>Open modal</button>
<dialog id="testDialog">
<h1>An example of a native Dialog element</h1>
<p>This is a dialog box and, believe it or not, it's built into HTML, sure we needed some javascript to open it but hey, it's a start.</p>
<button data-modal-for="testDialog" close>Close modal</button>
</dialog>
dialog {
border: none;
border-radius: 2px;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
max-width: 60vw;
}
const modalTriggers = document.querySelectorAll(`[data-modal-for]`);
for (let trigger of modalTriggers) {
const modal = document.getElementById(trigger.dataset.modalFor);
trigger.addEventListener('click', () => {
trigger.hasAttribute('open') && modal.showModal();
trigger.hasAttribute('close') && modal.close();
});
}
Here's how it looks after pressing the button, in a supported browser.
Explain the javascript
I'm going to presume you know what the javascript does so I'm going to explain why I've done it this way.
First, I select all the elements I've given the data-modal-for
attribute to then I add eventListeners to them. I also give my trigger
elements an open
or close
attribute to specify how they will change the dialog
I know that this means any dynamically created elements won't work out the box but this was still the best way I could think of.
Signing off
Let me know if you like these things we can't really use yet but maybe one day
posts. I find the advancement of the platform interesting and enjoy sharing.
Thanks for reading 🦄🦄😀😀❤🦄