dialog
Kennzeichnet einen Container als modalen oder nicht-modalen Dialog. Das native <dialog>-Element mit showModal() übernimmt Fokusfalle, Top-Layer, Hintergrundblende und Escape-Schließen automatisch. role="dialog" sollte nur verwendet werden, wenn das native Element nicht möglich ist.
Verwendung
Das <dialog>-Element sollte per .showModal() geöffnet werden. Das native Element wird in allen aktuellen Browsern unterstützt und übernimmt automatisch die Inertisierung des Hintergrunds, die Fokusfalle, das Schließen per Escape, den ::backdrop-Styling-Hook und das Top-Layer-Rendering. Dadurch entfallen etwa 200 Zeilen fehleranfälliges JavaScript.
role="dialog" auf einem <div> sollte nur verwendet werden, wenn:
- Browser älter als Chrome 37 / Firefox 98 / Safari 15.4 unterstützt werden müssen (in 2026 unwahrscheinlich).
- Das Design einen Dialog verlangt, der nicht im Top-Layer leben kann (selten).
- Ein unzugängliches Custom-Modal während eines Refactorings gepatcht wird.
Jeder Dialog MUSS einen zugänglichen Namen haben (aria-labelledby auf eine sichtbare Überschrift ist das stärkste Muster). Modale Dialoge benötigen zusätzlich aria-modal="true".
Tastatur- und Fokusvertrag
Gemäß dem APG-Muster für modale Dialoge:
- Beim Öffnen wandert der Fokus zum ersten fokussierbaren Element im Dialog (häufig dem Schließen-Button oder dem primären Eingabefeld).
- Tab und Shift+Tab bewegen den Fokus NUR innerhalb des Dialogs – eine „Fokusfalle“. Tab vom letzten Element kehrt zum ersten zurück; Shift+Tab vom ersten zum letzten.
- Escape schließt den Dialog.
- Beim Schließen kehrt der Fokus zu dem Element zurück, das den Dialog geöffnet hat. Das Speichern und Wiederherstellen des Fokus ist nicht verhandelbar; Nutzende, die ihren Ausgangspunkt verlieren, haben keinen Anker mehr.
- Der Rest der Seite ist
inert(oder als Fallbackaria-hidden="true"plus nicht fokussierbar), solange der Dialog geöffnet ist.
Häufige Fehler
- Custom-Dialog ohne Fokusfalle: Tab verlässt den Dialog und landet dahinter; Nutzende verlieren den Kontext.
- Fokus wird beim Schließen nicht zum auslösenden Element zurückgekehrt: Das nächste Tab landet auf dem Dokumentkörper.
- Hintergrundinhalt bleibt per Tab erreichbar, obwohl er optisch hinter dem Dialog verborgen ist.
- Kein zugänglicher Name: Der Dialog öffnet sich, und der Screenreader kündigt lediglich „Dialog“ an.
- Custom-Dialog ohne
aria-modal="true"— assistive Technologie behandelt ihn als Inline-Inhalt. - Escape schließt den Dialog, aber der Dialog ist über ein Portal gerendert, das beim Schließen die Tastatursteuerung verliert.
Beispiel
<!-- Bevorzugt -->
<dialog id="confirm">
<h2>Delete this draft?</h2>
<p>This cannot be undone.</p>
<form method="dialog">
<button value="cancel">Cancel</button>
<button value="delete" autofocus>Delete</button>
</form>
</dialog>
<script>
document.getElementById('confirm').showModal();
</script>
<!-- Wenn <dialog> nicht möglich ist -->
<div role="dialog" aria-modal="true" aria-labelledby="dlgTitle">
<h2 id="dlgTitle">Edit profile</h2>
…
</div>