I currently have a <dialog>
which I am opening via JS. For demonstration purposes, my dialog has a single <button>
element within it.
My issue is, when I open the dialog using .showModal()
, the button within the modal gets focused for some reason. See example of issue below:
const dialog = document.querySelector("#dialog");
document.querySelector("#open-btn").addEventListener('click', () => {
dialog.showModal();
});
document.querySelector("#close-btn").addEventListener('click', () => {
dialog.close();
});
#close-btn:focus {
background: red;
}
<button id="open-btn">Open</button>
<dialog id="dialog">
<button id="close-btn">×</button>
</dialog>
As you can see, when the dialog is opened, the background of the button within the dialog gets the :focus
styles applied, showing that it is focused.
My question is: Why is this happening? My expected behaviour would be for the dialog to open and for the button to not be focused when opening the dialog. I'm aware that I can .blur()
the close button programatically, but that feels like I'm just "hiding" the issue rather than addressing the thing that's actually causing it.
Note: This issue is present in the latest version of Google Chrome (Version 81.0.4044.138)
This is expected behavior for a modal dialog UI pattern and is important to not override for accessibility reasons. Calling blur()
on the dialog's child button will dump focus on the HTML body element and likely cause problems for users of assistive technology such as those using screen reader software.
If you prefer not to have the dialog's child button have a visual focus style when the dialog is opened, style the button using the CSS :focus-visible
pseudo class.
In the code snippet below you will see that when clicking the open and close buttons those buttons will not receive visual focus, but when using your keyboard by tabbing to the buttons and opening them using the Enter or Space keys, they will. Showing visual focus is important for usability for keyboard only users and for not violating the Web Content Accessibility Guidelines (reference 1, reference 2). You should always make sure to help keyboard users know where they are in the DOM by not removing focus indicators or doing things like calling blur()
immediately after a focus event occurs.
const openButton = document.querySelector("button.open-dialog");
const closeButton = document.querySelector("button.close-dialog");
const dialog = document.querySelector("dialog");
openButton.addEventListener("click", () => {
dialog.showModal();
});
closeButton.addEventListener("click", () => {
dialog.close();
});
button:focus-visible {
outline: 3px solid blue;
}
<button class="open-dialog">Open dialog</button>
<dialog>
<h2>I am a dialog</h2>
<button class="close-dialog">close</button>
</dialog>