# Creating modal dialogs with the HTML `dialog` element

ID:

Technology: html

Type: Technique

## When to Use

HTML

## Description

Website authors often use modal dialogs to focus a user's attention on information, or a task-related activity beyond the scope of the primary page's content. Modal dialogs can be built in markup using ARIA's dialog role and related attributes, or the HTML's `dialog` element. As well as meeting the first rule of ARIA, the HTML `dialog` element offers several advantages to its ARIA counterpart, with the browser handling these features:

- keyboard focus is moved to the newly-opened modal `dialog`;
- keyboard focus returns to the invoking element (assuming the element is still on the page) when the modal `dialog` is closed;
- keyboard focus is limited to the contents of the modal `dialog` and the browser's chrome (e.g., the browser-specific UI, such as the address bar, etc.);
- the page's content 'outside' of the modal dialog becomes inert, resulting in the content becoming hidden from assistive technologies, and inoperable to all users, so long as the modal `dialog` remains open;
- the use of the `Escape` key to close the modal `dialog`.

This technique uses the HTML `dialog` element rather than a custom ARIA implementation, reducing the level of effort to create an accessible modal dialog.

## Examples

### A dialog to sign up to a mailing list

This is an example of using a modal `dialog` element to show a mailing-list sign-up form to a user. The main part of the page contains a `button` element that, when activated, invokes the modal `dialog`. The `button` uses the `type` attribute to tell the browser that this isn't a `submit` `button`.

When the modal `dialog` is opened, the browser will treat all content outside of the modal dialog as inert, rendering it inoperable and hiding the content from assistive technology. For example, a screen reader will not be able to reach or announce any of the inert content. Additionally, because the page content is inert, keyboard focus will only be able to reach focusable elements within the `dialog` element, and the browser's controls. When invoked, the browser automatically sets focus to the first focusable element in the dialog's DOM. In this example the `h1` element will receive focus because it has a `tabindex="-1"` attribute. Note that, although the `dialog`'s close `button` is visibly before the `h1`, it is the last item in the `dialog`'s DOM. If the `button` was first, it would receive focus when dialog was opened.

#### The HTML

    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,
         initial-scale=1, shrink-to-fit=no">
        <title>Turbo Encabulator News</title>
      </head>
      <body>
        <main>
          <h1>All The News About Turbo Encabulators</h1>
          <button class="open-modal" type="button">Sign up to our mailing list!</button>
        </main>
        <dialog aria-labelledby="dialog-heading" id="mailing-list-dialog">
          <h1 id="dialog-heading" tabindex="-1">Sign up to our mailing list</h1>
          <form>
            <p class="req-note">All form fields are required.</p>
            <div>
              <label for="fname">First Name</label>
              <input aria-required="true" autocomplete="given-name" id="fname" type="text">
            </div>
            <div>
              <label for="lname">Last Name</label>
              <input aria-required="true" autocomplete="family-name" id="lname" type="text">
            </div>
            <div>
              <label for="email">Email address</label>
              <input aria-required="true" autocomplete="email" id="email" type="text">
            </div>
            <button class="sign-up" type="submit">Sign up</button>
          </form>
         <form method="dialog">
            <button aria-label="close" class="close-modal">&times;</button>
          </form>
        </dialog>
      </body>
    </html>

#### The CSS

    *, *::after, *::before {
      box-sizing: inherit;
    }

    body {
      background:#fff;
      color:#000;
      font:1rem/1.5 system-ui, Helvetica, Roboto, sans-serif;
    }

    *:focus-visible {
      outline:1px solid #0054AE;
      outline-offset:1px;
    }

    dialog {
      border:1px solid #000;
      padding:2rem;
      position:relative;
    }

    dialog::backdrop {
      background-color:hsla(0, 0%, 0%, .5);
    }

    .close-modal {
      inset-block-start:1.5rem;
      inset-inline-end:1.5rem;
      line-height:1.3;
      padding:0.25em 0.5em;
      position:absolute;
    }

    .sign-up {
      background:#000;
      color:#fff;
      padding:0.25em;
    }

    dialog h1 {
      display:inline-block;
      line-height:1.3333;
      margin:0;
      max-inline-size:95%;
    }

    form {
      display:grid;
      grid-gap:20px;
      grid-template-columns:repeat(auto-fit, minmax(150px, 1fr));
    }

    .req-note, .sign-up {
      grid-column:1 / -1;
    }

    label {
      display:block;
    }

    input {
      border:1px solid hsl(0, 0%, 50%);
      font:inherit;
      inline-size:calc(100% - 4px);
    }

    button {
      background:#fff;
      border:1px solid hsl(0, 0%, 50%);
      border-radius:3px;
      color:inherit;
      font:inherit;
      margin:0;
    }

#### The JavaScript

The script is necessary to display the `dialog` when invoked. The HTML `dialog` element can be opened using two different commands: `show()` (for non-modal `dialog`s), and `showModal()` (for modal `dialog`s) - used in this example.

Note: instead of writing a function to close the `dialog`, the close button is nested within a separate `form` element with a `method="dialog"` attribute. This method allows the dialog to be closed when activating this button, and the browser will handle returning keyboard focus to the invoking element,

    document.addEventListener("DOMContentLoaded", function(e){
      const d = document.querySelector("dialog");
      const btnOpen = document.querySelector(".open-modal");

      btnOpen.addEventListener("click", function(){
        d.showModal();
      }, false);

    });

## Tests

### Procedure

1. Find the components on the page that invoke modal `dialog` elements.
2. Check that each `dialog` can be opened using the keyboard to activate the invoking element (for example, activate a `button` by pressing the `Enter` key or `Spacebar`.
3. When the modal `dialog` is opened, check that focus has moved to it / one of its focusable descendants.
4. While the modal `dialog` is open, check that keyboard focus cannot move to elements of the primary document.
5. When the modal `dialog` is closed, check that focus is placed back onto the invoking element, if the element still exists on the page.

### Expected Results

- Checks #2, #3, #4 and #5 are true.

## Related Techniques

- SCR26
- G59

## Resources

- HTML - the `dialog` element.
- HTML - the `button` element.
- ARIA Authoring Practices Guide - dialog (modal) pattern.
- Using ARIA.