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. Keinez-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:
- Interaktion wird blockiert. Alles außerhalb des Dialogs wird inaktiv — Klicks und Tastatureingaben erreichen die Seite dahinter nicht mehr.
- Ein Backdrop erscheint. Der Browser rendert das
::backdrop-Pseudoelement hinter dem Dialog, das Sie gestalten können. - Fokus wird eingeschränkt. Das Tabben wechselt nur zwischen den fokussierbaren Elementen innerhalb des Dialogs.
- 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>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:
| Ereignis | Wann es ausgelöst wird |
|---|---|
close | Immer wenn der Dialog geschlossen wird — durch close(), durch Absenden eines method="dialog"-Formulars oder durch Esc. Hier returnValue auslesen. |
cancel | Wenn 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-labelledbyauf die ID der Überschrift des Dialogs, damit Screenreader seinen Titel ankündigen. Verwenden Siearia-describedbyfü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 demautofocus-Attribut markieren. Platzieren Sieautofocusbevorzugt 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
| Attribut | Wert | Beschreibung |
|---|---|---|
open | open | boolean-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.