3

O dialog focus, where art thou?

 1 year ago
source link: https://www.matuzo.at/blog/2023/focus-dialog/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

O dialog focus, where art thou?

posted on July 17., 2023

Here’s a job interview question for you: When you click a button and call the showModal() method to open a modal <dialog>, where does the focus go by default, and how can you move it elsewhere?

Don't know the answer? Neither did I, so I tested it.

OS/Browsers

macOs 13.4.1 Ventura
Chrome 114
Firefox 115
Safari 16.5.1

Here’s a Codepen with all demos so you can follow along.

Demo 1: Dialog with no interactive element

<button>demo 1</button>

<dialog>
<h1>Demo 1</h2>
</dialog>
document.addEventListener('click', e => {
if (e.target.closest('button')) {
e.target.nextElementSibling.showModal()
}
})

Focus is on:

Chrome: dialog
Firefox: body
Safari: body

Demo 2: Dialog with interactive elements

<button>demo 2</button>

<dialog>
<h1>Demo 2</h2>

<button>First focusable element</button>
<a href="#">Last focusable element</a>
</dialog>

Focus is on:

Chrome: first focusable element
Firefox: first focusable element
Safari: first focusable element

Demo 3: Dialog with interactive elements and close button first


<button>demo 3</button>

<dialog>
<form method="dialog">
<button>close</button>
</form>

<h1>Demo 3</h2>

<button>First focusable element</button>
<a href="#">Last focusable element</a>
</dialog>

Focus is on:

Chrome: close button
Firefox: close button
Safari: first focusable element after close button

Demo 4: Dialog with interactive elements and close button last

<button>demo 4</button>

<dialog>
<h1>Demo 4</h2>

<button>First focusable element</button>
<a href="#">Last focusable element</a>

<form method="dialog">
<button>close</button>
</form>
</dialog>

Focus is on:

Chrome: first focusable element
Firefox: first focusable element
Safari: first focusable element

Demo 5: Dialog without interactive elements and autofocus on dialog

<button>demo 5</button>

<dialog autofocus>
<h1>Demo 5</h2>
</dialog>

Focus is on:

Chrome: dialog
Firefox: body
Safari: body

Demo 6: Dialog with interactive elements and autofocus on dialog

<button>demo 6</button>

<dialog autofocus>
<h1>Demo 6</h2>

<button>First focusable element</button>
<a href="#">Last focusable element</a>
</dialog>

Focus is on:

Chrome: first focusable element
Firefox: first focusable element
Safari: first focusable element

Demo 7: Dialog with autofocus on last interactive element

<button>demo 7</button>

<dialog>
<h1>Demo 7</h2>

<button>First focusable element</button>
<a href="#" autofocus>Last focusable element</a>
</dialog>

Focus is on:

Chrome: last focusable element
Firefox: last focusable element
Safari: last focusable element

Okay, so far, so inconsistent. The specs says “The tabindex attribute must not be specified on dialog elements.”.

I won't do what you tell me.

– Rage Against the Machine

Demo 8: Dialog with tabindex and no interactive element

<button>demo 8</button>

<dialog tabindex="-1">
<h1>Demo 8</h2>
</dialog>

Focus is on:

Chrome: dialog
Firefox: dialog
Safari: dialog

Demo 9: Dialog with tabindex and interactive elements

<button>demo 9</button>

<dialog tabindex="-1">
<h1>Demo 9</h2>

<button>First focusable element</button>
<a href="#">Last focusable element</a>
</dialog>

Focus is on:

Chrome: first focusable element
Firefox: first focusable element
Safari: first focusable element

Demo 10: Dialog with tabindex, autofocus, and interactive elements

<button>demo 10</button>

<dialog tabindex="-1" autofocus>
<h1>Demo 10</h2>

<button>First focusable element</button>
<a href="#">Last focusable element</a>
</dialog>

Chrome: first focusable element
Firefox: first focusable element
Safari: first focusable element

Demo 11: Dialog with tabindex, focus(), and interactive elements

<button>demo 11</button>

<dialog tabindex="-1">
<h1>Demo 11</h2>

<button>First focusable element</button>
<a href="#">Last focusable element</a>
</dialog>
dialog.showModal()
dialog.focus()

Focus is on:

Chrome: dialog
Firefox: dialog
Safari: dialog

Conclusion

The answer is: It depends. It depends on several factors:

  • The browser you're using.
  • The presence of interactive elements.
  • The presence of a dialog close button.
  • The presence of the autofocus attribute.
  • The presence of the tabindex attribute.

There was a lot of discussion on how browsers should handle focus in modal dialogs. They finally concluded and summarized the rules in the spec earlier this year. If I read it right, Chrome is the only browser that follows most rules correctly at this point. Other browsers will likely follow soon.

Right now you get the most consistent behaviour when:

  • you have interactive elements and do nothing
  • you put the autofocus attribute on one of the interactive elements
  • you put tabindex=-1 on the dialog (and focus() it).

Updates

20.7.2023: Changed body to first focusable element for Chrome in demo 6 and demo 10. I had experimental web platform features enabled, which changed the current default behaviour.

My blog doesn't support comments yet, but you can reply via e-mail.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK