Start · Sprachen · JavaScript · Referenz · HTMLDialogElement.showModal()

HTMLDialogElement.showModal()

Methode

Öffnet ein <code>&lt;dialog&gt;</code>-Element als modalen Dialog in der Top-Layer-Ebene, macht den restlichen Seiteninhalt inert und zeigt einen <code>::backdrop</code> an.

seit JavaScript Baseline: alle modernen Browser seit März 2022 (Ch Kategorie: webapi

Signatur

HTMLDialogElement.prototype.showModal()

Beschreibung

showModal() öffnet ein <dialog>-Element als modalen Dialog. Der Dialog wird in die sogenannte Top Layer verschoben und liegt damit unabhängig von z-index oder overflow der Elternelemente über allen anderen Inhalten. Hinter dem Dialog wird das Pseudo-Element ::backdrop gerendert, das sich per CSS gestalten lässt, z. B. als halbtransparente Abdunkelung.

Solange der Dialog modal geöffnet ist, ist der restliche Dokumentinhalt inert: Er lässt sich weder anklicken noch per Tastatur fokussieren und ist für assistive Technologien ausgeblendet. Der Fokus springt automatisch auf das erste fokussierbare Element im Dialog (oder auf ein Element mit dem Attribut autofocus). Mit der Esc-Taste lässt sich der Dialog schließen. Dabei wird zuerst das Ereignis cancel und danach close ausgelöst.

Verwende showModal() für Bestätigungsabfragen, Formulare oder Hinweise, die die volle Aufmerksamkeit brauchen, bevor der Nutzer weiterarbeiten kann. Für nicht-modale Einblendungen, bei denen die Seite bedienbar bleiben soll, nimmst du show(). Geschlossen wird der Dialog mit close(returnValue) oder über ein Formular mit method="dialog".

Rückgabewert

Typ
void
Beschreibung
Gibt undefined zurück. Unter bestimmten Bedingungen wird eine DOMException geworfen (siehe Hinweise).

Beispiele

Modalen Dialog per Button öffnen und schließen

// HTML:
// <button id="open">Einstellungen</button>
// <dialog id="settings">
//   <p>Einstellungen …</p>
//   <button id="close">Schließen</button>
// </dialog>

const dialog = document.querySelector('#settings');

document.querySelector('#open').addEventListener('click', () => {
  dialog.showModal();
  console.log('offen:', dialog.open);
});

document.querySelector('#close').addEventListener('click', () => {
  dialog.close();
  console.log('offen:', dialog.open);
});
offen: true offen: false

Bestätigungsdialog mit Promise und returnValue

// HTML:
// <dialog id="confirm">
//   <form method="dialog">
//     <p>Eintrag wirklich löschen?</p>
//     <button value="cancel">Abbrechen</button>
//     <button value="ok" autofocus>Löschen</button>
//   </form>
// </dialog>

const confirmDialog = (dialog) =>
  new Promise((resolve) => {
    dialog.returnValue = '';
    dialog.addEventListener(
      'close',
      () => resolve(dialog.returnValue === 'ok'),
      { once: true }
    );
    dialog.showModal();
  });

const handleDelete = async () => {
  const ok = await confirmDialog(document.querySelector('#confirm'));
  console.log(ok ? 'Wird gelöscht' : 'Abgebrochen');
};

handleDelete();
Wird gelöscht // nach Klick auf „Löschen“

Schließen per Klick auf den Backdrop und Esc abfangen

const dialog = document.querySelector('dialog');
dialog.showModal();

// Klick außerhalb des Inhalts trifft das <dialog>-Element selbst (Backdrop-Bereich)
dialog.addEventListener('click', (event) => {
  const rect = dialog.getBoundingClientRect();
  const inside =
    event.clientX >= rect.left && event.clientX <= rect.right &&
    event.clientY >= rect.top && event.clientY <= rect.bottom;
  if (!inside) dialog.close('backdrop');
});

// Esc verhindern, z. B. bei ungespeicherten Änderungen
dialog.addEventListener('cancel', (event) => {
  if (!confirm('Änderungen verwerfen?')) event.preventDefault();
});

dialog.addEventListener('close', () => {
  console.log('Geschlossen mit:', dialog.returnValue);
});
Geschlossen mit: backdrop

Sicher öffnen, ohne Exception

const openModalSafely = (dialog) => {
  if (!dialog.isConnected) return false;
  if (dialog.open && !dialog.matches(':modal')) dialog.close();
  if (!dialog.open) dialog.showModal();
  return dialog.matches(':modal');
};

console.log(openModalSafely(document.querySelector('dialog')));
true

// Wichtig · Fallstricke

  • Exceptions: Ist der Dialog bereits nicht-modal offen (über show() oder das Attribut open), wirft showModal() einen InvalidStateError. Das Gleiche passiert, wenn das Element nicht im Dokument hängt (isConnected === false) oder als Popover angezeigt wird. Ist der Dialog bereits modal offen, bleibt der Aufruf seit neueren Spezifikationsständen ohne Wirkung.
  • Nicht das Attribut open setzen: Mit dialog.open = true oder <dialog open> öffnet sich der Dialog nur nicht-modal. Dann gibt es weder Top Layer noch ::backdrop, kein Inert-Verhalten und kein Schließen per Esc.
  • Fokus: Beim Schließen geht der Fokus in modernen Browsern an das Element zurück, das vorher fokussiert war. Mit autofocus legst du fest, welches Element im Dialog den Anfangsfokus bekommt. Bei destruktiven Aktionen ist „Abbrechen“ als Anfangsfokus meist die sicherere Wahl.
  • Scrollen im Hintergrund: Die Seite hinter dem Dialog lässt sich weiter scrollen. Falls das stört, sperrst du es per CSS, z. B. mit body:has(dialog[open]) { overflow: hidden; }.
  • Esc-Taste: Chrome lässt einen Dialog nicht dauerhaft offen, wenn der Nutzer mehrfach Esc drückt, auch wenn cancel per preventDefault() abgefangen wird. Verlasse dich nicht darauf, dass sich das Schließen vollständig verhindern lässt.
  • Kompatibilität: Seit Firefox 98 und Safari 15.4 (2022) in allen modernen Browsern verfügbar. Für ältere Browser gibt es das Polyfill dialog-polyfill. Neuere Zusätze wie das Attribut closedby oder deklarative Befehle (command="show-modal") werden noch nicht überall unterstützt.