Posted on
Reading Time: 3 minutes

The `<dialog>` element has been around for years, and it was finally approved by the W3C in the HTML 5.2 spec. But how does it work? Is it fully supported?—and can we finally quit using `role=”dialog”`?

The answer to most of these questions is, “No.” In this article I will get into why, and in the next article I’ll show you the pattern to use instead.

The `<dialog>` element is supposed to be the long-awaited “Modal to rule them all”: a conclusive answer to the hodgepodge of dialog patterns that already exist in the wild. It should allow developers to cut down on requisite HTML attributes, Javascript and even CSS. It even (theoretically) traps keyboard focus!

Some of the completely dope features that the `<dialog>` is supposed to offer:

  • Special Javascript methods to show/hide the dialog: `dialog.showModal()` and `dialog.close()`
  • Set focus to the first focusable element (unless you use `tabindex` to override)
  • A pre-styled CSS backdrop and horizontal positioning
  • Listens for Esc key to close the dialog
  • When it closes, it can pass a data string to the `dialog.close()` method

I know, but don’t get excited just yet. Unfortunately, this native component still doesn’t have the minimal support to get developer backing.

Chrome (macOS+Windows) and the new Chromium-based Edge browser support `<dialog>` nicely, but Firefox is a mess. Even with a feature flag enabled in Firefox preferences, and with polyfill support, the dialog element fails to trap keyboard focus – and in VoiceOver (macOS), it fails to trap screen reader focus as well. Safari does not support it at all, and don’t even get me started with Internet Explorer.

Accessibility Behavior Windows JAWS-Chrome Windows JAWS-Firefox Windows JAWS-Edge Windows NVDA-Chrome Windows NVDA-Firefox Windows NVDA-Edge Windows JAWS/NVDA-IE macOS VO-Chrome macOS VO-Firefox macOS/iOS VO-Safari
Announce Dialog Context Pass – “Modal dialog” Pass – “Dialog” Pass – “Modal dialog” Fail – null Fail – null Fail – null Fail – null Fail – “Group” Fail – “Group” Fail – null
Hide & Show Pass Pass Pass Pass Pass Pass Fail Pass Pass Fail
Trap Keyboard Focus Pass Fail Pass Pass Fail Pass Fail Pass Fail Fail
Trap Screen Reader Focus Pass Pass Pass Pass Pass Pass Fail Pass Fail Fail
CSS Styling Pass Pass Pass Pass Pass Pass Fail Pass Pass Fail

The MDN specs for the dialog element claim that there is a polyfill to extend support for browsers without the `<dialog>` element, but it confers no noticeable improvement.

The MDN documentation also puts Firefox behind a feature flag (about:config, dom.dialog_element.enabled), but let’s take a look at the result of enabling this property.

Windows/JAWS on Firefox (w/polyfill)

  • Feature flag = “false”: (1) Can’t handle `tabindex`, (2) Traps keyboard and screen reader focus
  • Feature flag = “true”: (1) OK with `tabindex`, (2) Traps screen reader focus, but NOT keyboard focus

Windows/NVDA on Firefox (w/polyfill)

  • Feature flag = “false”: Works OK
  • Feature flag = “true”: DOES NOT trap keyboard focus

macOS/VoiceOver on Firefox (w/polyfill)

  • Feature flag = “false”: (1) Traps keyboard and screen reader focus, (2) Announces “dialog” role
  • Feature flag = “true”: (1) Traps screen reader focus, but NOT keyboard focus, (2)  DOES NOT announce “dialog” role, announces “group”

In short, the feature flag that is supposed to fix the issue makes the issue marginally worse, at best. In a way, it performs an abuse on the experience, and in a very small minority of cases that abuse builds some valuable character traits – but overall, the juice isn’t worth the squeeze.

Cartoon: Dad, Bug bites build character. Calvin, Yeah and last year you said diarrhea builds character. Dad, So think what a fine young man you're growing up to be. Calvin, If all this character doesn't kill me first.
Calvin and Hobbes: Image credit.

Even when Safari adds nominal support for the element, these lingering discrepancies will give developers pause when considering use of the `<dialog>` element for a wide audience. For the same reason, I won’t get into how to use it; plenty of prior authors have already done that (see References below). Instead, the next article will outline the still-best-case-ideal solution.