As I am aware, theshowModal() method runs the following steps which end up focusing elements within an HTML dialog (emphasis mine) :
Letsubject be the dialog element on which the method was invoked.
Ifsubject already has an open attribute, then throw an"InvalidStateError"DOMException.
Ifsubject is notconnected, then throw an"InvalidStateError"DOMException`.
Add an open attribute to subject, whose value is the empty string.
Set the dialog to the centered alignment mode.
Letsubject'snode document beblocked by the modaldialogsubject.
Ifsubject'snode document'stoplayer does not alreadycontainsubject, thenaddsubject tosubject'snode document'stoplayer.
Run thedialog focusing steps forsubject.
So the last step,8, will run the followingdialog focusing steps on the dialog. From my understanding (which could be completely wrong), these three steps from the dialog focusing-steps section of the spec specify that the element should only be focused if the element is not inert and is auto-focusable:
If subject isinert, return.
Let control be the first descendant element of the subject, intree order, that is notinert and has the autofocus attribute specified.
If there isn't one, then let control be the first non-inert descendantelement ofsubject, in tree order.
If there isn't one of those either, then let control be subject.
Run thefocusing steps for control.
...
So, to me, it seems as though if my button below (see snippet) has theinert attribute or is not auto-focusable then it shouldn't get focused when the dialog opens. However, when I try and apply both attributes, it still ends up being focused.
Attempt with theinert boolean attribute (which I thought would've made the dialog focusing stepsreturn above, hence performing no focusing):
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>Open</button><dialog> <button inert="inert">×</button></dialog>Attempt with theautofocus boolean attribute set to false (I believe this is how you set it to false, I also triedautofocus="false" which didn't work either):
update 2023: It appears the below hidden snippet usinginert now does stop the button from being autofocused (when I asked this question it didn't, which I suspect was a chrome bug), however it stops the button from being clickable, so this isn't a valid option.
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>Open</button><dialog> <button autofocus="">×</button></dialog>With both of these failing to work, I searched SO and foundthis answer which suggested that I might also be able to usetabindex="-1", which didn't work either.
I'm aware that I can blur the button once it is focusedusing.blur(), but my question specifically is:
- Why don't the two fiddles above disable the button from being automatically focused?
- Is there an HTML attribute of some sort that I can use to stop my button from being focused?
- Related GitHub issue:github.com/whatwg/html/issues/1929shreyasm-dev– shreyasm-dev2020-08-11 18:36:36 +00:00CommentedAug 11, 2020 at 18:36
2 Answers2
Disabled elements cannot be focused on. You could add thedisabled attribute toclose-btn.
But, disabled elements cannot be clicked. Add the onclick attribute toopen-btn. Set theonclick to this:setTimeout(function(){document.getElementById('close-btn').disabled = false}). This just enables the button 1 millisecond after the button is clicked. The timeout is required so that it does not enableclose-btn before the dialog is opened.
If the dialog is re-opened, The button is automatically focused. We could add another onclick attribute toclose-btn. Setonclick onclose.btn to this:this.disabled = true. This disablesclose-btn when it is clicked.
Final result:
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 onclick='setTimeout(function(){document.getElementById("close-btn").disabled = false})'>Open</button><dialog> <button disabled inert="inert" onclick='this.disabled = true'>×</button></dialog>Comments
maybe this would work, it did to me
BeingselectorElement the actual element we want to dont show the outline when is focused
selectorElement:focus-visible { outline: none;}Comments
Explore related questions
See similar questions with these tags.

