7

As I am aware, theshowModal() method runs the following steps which end up focusing elements within an HTML dialog (emphasis mine) :

  1. Letsubject be the dialog element on which the method was invoked.

  2. Ifsubject already has an open attribute, then throw an"InvalidStateError"DOMException.

  3. Ifsubject is notconnected, then throw an"InvalidStateError"DOMException`.

  4. Add an open attribute to subject, whose value is the empty string.

  5. Set the dialog to the centered alignment mode.

  6. Letsubject'snode document beblocked by the modaldialogsubject.

  7. Ifsubject'snode document'stoplayer does not alreadycontainsubject, thenaddsubject tosubject'snode document'stoplayer.

  8. 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:

  1. If subject isinert, return.

  2. 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.

  3. 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">&times;</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="">&times;</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:

  1. Why don't the two fiddles above disable the button from being automatically focused?
  2. Is there an HTML attribute of some sort that I can use to stop my button from being focused?
askedAug 5, 2020 at 14:40
Shnick's user avatar
1

2 Answers2

0

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'>&times;</button></dialog>

answeredAug 11, 2020 at 18:53
shreyasm-dev's user avatar
Sign up to request clarification or add additional context in comments.

Comments

0

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;}
answeredSep 15, 2023 at 17:31
Alejandro Sánchez Durán's user avatar

Comments

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.