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 seems default behavior defined in the standard to focus the modal subtree once its rendered, from the HTML live standard:
- Run the dialog focusing steps for subject.
If you want to keep it like this and prevent the button from focus just trigger blur()
event on the button, I tried to use inert
and autofocus
attributes but they doesn't seems to work work, so I think you have to stick with .blur()
implementation:
const dialog = document.querySelector("#dialog");
document.querySelector("#open-btn").addEventListener('click', () => {
dialog.showModal();
document.getElementById('close-btn').blur();
});
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" inert="false" autofocus="false">×</button>
</dialog>