W3docs

HTML <dialog>-Tag

HTML <dialog>-Tag: show() vs. showModal(), form method="dialog", close- und cancel-Ereignisse sowie Barrierefreiheit.

Der <dialog>-Tag ist eines der HTML5-Elemente. Er erstellt ein natives Dialogfeld — ein Pop-up-Panel wie eine Bestätigungsmeldung, ein Hinweis oder ein Formular —, mit dem der Benutzer interagiert, bevor er fortfährt. Das Dialogfeld ist standardmäßig ausgeblendet und wird über eine kleine JavaScript-API ein- und ausgeblendet.

Diese Seite behandelt die zwei Möglichkeiten, einen Dialog zu öffnen (show() und showModal()), wie man ihn schließt und sein Ergebnis ausliest, das <form method="dialog">-Muster, die close- und cancel-Ereignisse, Barrierefreiheit sowie das Styling des Backdrops.

Warum nativer <dialog> statt einem selbst erstellten <div>-Modal?

Vor <dialog> bauten Entwickler Modals aus einem <div> mit einer Reihe von CSS und JavaScript von Hand. Das native Element erledigt diese Arbeit für Sie — und das zuverlässiger:

  • Eingebaute Fokusfalle. Beim Öffnen mit showModal() bleibt der Tastaturfokus (Tab / Shift+Tab) innerhalb des Dialogs. Ein <div>-Modal muss den Fokus manuell einschränken, und Fehler dabei sind ein häufiger Barrierefreiheitsfehler.
  • Top-Layer-Stapelung. Ein modaler Dialog wird im Top Layer des Browsers gerendert und überdeckt daher immer den Rest der Seite, unabhängig von z-index. Keine z-index-Konflikte mehr.
  • Automatischer Backdrop. showModal() zeichnet ein ::backdrop-Pseudoelement hinter dem Dialog, das Klicks auf die darunterliegende Seite blockiert — kein zusätzliches Overlay-Element nötig.
  • Esc zum Schließen. Das Drücken von Esc schließt einen modalen Dialog automatisch (und löst ein cancel-Ereignis aus, auf das Sie reagieren können).
  • Echte Semantik. Das Element trägt eine implizite role="dialog", sodass assistive Technologien es korrekt ankündigen, ohne zusätzliche ARIA-Attribute.

Syntax

Der <dialog>-Tag wird paarweise verwendet. Platzieren Sie den Dialoginhalt zwischen dem öffnenden (<dialog>) und dem schließenden (</dialog>) Tag. Sie öffnen ihn per Skript mit einer der zwei Methoden des DOM-Objekts des Elements:

  • dialog.show() — öffnet einen nicht-modalen Dialog.
  • dialog.showModal() — öffnet einen modalen Dialog.
  • dialog.close([returnValue]) — schließt den Dialog und speichert optional einen Rückgabewert.

Das boolean-Attribut open gibt an, ob der Dialog aktuell angezeigt wird. In der Regel setzen Sie es nicht manuell; die oben genannten Methoden verwalten es für Sie.

Nicht-modale Dialoge: show()

show() öffnet den Dialog an Ort und Stelle, ohne die Seite zu blockieren. Der Rest des Dokuments bleibt interaktiv, es gibt kein ::backdrop, der Fokus ist nicht eingeschränkt, und Esc schließt ihn nicht. Dies ist die richtige Wahl für unkritische, schließbare Panels wie eine kleine Werkzeugbox, einen „Was ist neu"-Hinweis oder eine eingebettete Auswahl.

<!DOCTYPE html>
<html>
  <head>
    <title>Non-modal dialog with show()</title>
  </head>
  <body>
    <button id="open">Open non-modal dialog</button>

    <dialog id="info">
      <p>You can still click and scroll the page behind me.</p>
      <button id="close">Close</button>
    </dialog>

    <script>
      const dialog = document.getElementById("info");

      document.getElementById("open").addEventListener("click", () => {
        dialog.show();
      });

      document.getElementById("close").addEventListener("click", () => {
        dialog.close();
      });
    </script>
  </body>
</html>

Modale Dialoge: showModal()

showModal() öffnet den Dialog als Modal. Dadurch ändert sich das Verhalten in vier wichtigen Punkten:

  1. Interaktion wird blockiert. Alles außerhalb des Dialogs wird inaktiv — Klicks und Tastatureingaben erreichen die Seite dahinter nicht mehr.
  2. Ein Backdrop erscheint. Der Browser rendert das ::backdrop-Pseudoelement hinter dem Dialog, das Sie gestalten können.
  3. Fokus wird eingeschränkt. Das Tabben wechselt nur zwischen den fokussierbaren Elementen innerhalb des Dialogs.
  4. Er wird in den Top Layer aufgenommen. Der Dialog wird über allen anderen Inhalten gerendert und ignoriert dabei z-index. Das Drücken von Esc schließt ihn.
<!DOCTYPE html>
<html>
  <head>
    <title>Modal dialog with showModal()</title>
    <style>
      dialog {
        width: 40%;
        border: 1px solid #ccc;
        border-radius: 0.5em;
        padding: 1em;
      }
      dialog::backdrop {
        background-color: rgba(0, 0, 0, 0.5);
      }
    </style>
  </head>
  <body>
    <button id="open">Open modal dialog</button>

    <dialog id="confirm">
      <p>The page behind is blocked. Press Esc or a button to close.</p>
      <button id="close">Close dialog</button>
    </dialog>

    <script>
      const dialog = document.getElementById("confirm");

      document.getElementById("open").addEventListener("click", () => {
        dialog.showModal();
      });

      document.getElementById("close").addEventListener("click", () => {
        dialog.close();
      });
    </script>
  </body>
</html>
Result

Das <form method="dialog">-Muster

Ein <form> innerhalb eines <dialog> kann method="dialog" verwenden. Das Absenden eines solchen Formulars schließt den Dialog, ohne eine Netzwerkanfrage zu senden, und der Wert des geklickten Submit-<button>s wird in der returnValue-DOM-Eigenschaft des Dialogs gespeichert. Damit lässt sich leicht feststellen, welchen Button der Benutzer gewählt hat.

<!DOCTYPE html>
<html>
  <head>
    <title>Dialog with a form</title>
  </head>
  <body>
    <button id="open">Delete file</button>
    <p id="result"></p>

    <dialog id="confirm">
      <form method="dialog">
        <p>Are you sure you want to delete this file?</p>
        <button value="cancel">Cancel</button>
        <button value="delete">Delete</button>
      </form>
    </dialog>

    <script>
      const dialog = document.getElementById("confirm");
      const result = document.getElementById("result");

      document.getElementById("open").addEventListener("click", () => {
        dialog.showModal();
      });

      dialog.addEventListener("close", () => {
        // returnValue is the value of the button that submitted the form
        result.textContent = "You chose: " + dialog.returnValue;
      });
    </script>
  </body>
</html>

returnValue ist eine Eigenschaft des DOM-Elements, kein HTML-Attribut — Sie lesen oder setzen sie in JavaScript. Sie können sie auch direkt beim Schließen per Code setzen: dialog.close("delete").

Die close- und cancel-Ereignisse

Ein <dialog> löst zwei Ereignisse aus, auf die Sie hören können:

EreignisWann es ausgelöst wird
closeImmer wenn der Dialog geschlossen wird — durch close(), durch Absenden eines method="dialog"-Formulars oder durch Esc. Hier returnValue auslesen.
cancelWenn der Benutzer einen modalen Dialog mit der Esc-Taste schließt. Wird vor close ausgelöst. event.preventDefault() aufrufen, um den Dialog offen zu halten.
<dialog id="editor">
  <p>Unsaved changes — Esc would normally close me.</p>
  <button onclick="this.closest('dialog').close()">Done</button>
</dialog>

<script>
  const dialog = document.getElementById("editor");

  dialog.addEventListener("cancel", (event) => {
    // Prevent Esc from discarding unsaved work
    event.preventDefault();
  });

  dialog.addEventListener("close", () => {
    console.log("Dialog closed");
  });
</script>

Weitere Informationen zum Einbinden dieser Listener finden Sie unter JavaScript-Ereignisse und JavaScript HTML DOM.

Barrierefreiheit

Ein <dialog> hat eine implizite role="dialog", aber Sie müssen ihm dennoch einen zugänglichen Namen geben und den Fokus verwalten:

  • Dialog benennen. Verweisen Sie aria-labelledby auf die ID der Überschrift des Dialogs, damit Screenreader seinen Titel ankündigen. Verwenden Sie aria-describedby für eine ausführlichere Beschreibung.
  • Fokus beim Öffnen. showModal() verschiebt den Fokus automatisch in den Dialog — auf das erste fokussierbare Element oder ein Element, das Sie mit dem autofocus-Attribut markieren. Platzieren Sie autofocus bevorzugt auf einem sicheren Steuerelement (wie Abbrechen) statt auf einem destruktiven.
  • Fokus beim Schließen zurückgeben. Wenn der Dialog schließt, sollte der Fokus auf das Steuerelement zurückkehren, das ihn geöffnet hat, damit Tastaturbenutzer nicht an den Seitenanfang versetzt werden. Der Browser erledigt dies bei nativem <dialog> für Sie; für sicherste Ergebnisse speichern und stellen Sie den Auslöser selbst wieder her.
<button id="open">Edit profile</button>

<dialog id="profile" aria-labelledby="profile-title" aria-describedby="profile-desc">
  <h2 id="profile-title">Edit profile</h2>
  <p id="profile-desc">Update your display name, then save.</p>
  <form method="dialog">
    <input type="text" aria-label="Display name" autofocus>
    <button value="save">Save</button>
  </form>
</dialog>

<script>
  const openButton = document.getElementById("open");
  const dialog = document.getElementById("profile");

  openButton.addEventListener("click", () => dialog.showModal());

  // Explicitly return focus to the trigger when the dialog closes
  dialog.addEventListener("close", () => openButton.focus());
</script>

Weitere Informationen zum Erstellen barrierefreier interaktiver Widgets finden Sie unter DOM-Barrierefreiheitsüberlegungen.

Dialog und Backdrop gestalten

Sie können das Dialogfeld selbst und für modale Dialoge den Bereich dahinter mit dem ::backdrop-Pseudoelement gestalten.

dialog {
  border: 1px solid #ccc;
  border-radius: 0.5em;
  padding: 1em;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}

/* Only rendered for dialogs opened with showModal() */
dialog::backdrop {
  background-color: rgba(0, 0, 0, 0.5);
}

Attribute

AttributWertBeschreibung
openopenboolean-Attribut, das angibt, ob der Dialog aktuell angezeigt wird. Wird in der Regel durch show() / showModal() für Sie gesetzt.

Der <dialog>-Tag unterstützt außerdem die globalen Attribute und die Ereignisattribute.

Übungen

Übung
Welche Aussagen über das HTML-Element <dialog> sind korrekt?
Welche Aussagen über das HTML-Element <dialog> sind korrekt?
Was this page helpful?