dialog
Oznacza kontener jako modalne lub niemodalne okno dialogowe. Zalecane jest użycie natywnego elementu <dialog> z showModal() — obsługuje on pułapkę fokusa, warstwę najwyższą, tło i zamknięcie przez Escape bez dodatkowego kodu. Po role="dialog" sięgaj tylko gdy natywny element jest niemożliwy do zastosowania.
Kiedy stosować
Użyj <dialog> otwieranego przez .showModal(). Natywny element jest obsługiwany przez wszystkie aktualne przeglądarki, zarządza nieaktywnym tłem, pułapką fokusa, zamknięciem przez Escape, hakiem stylizacji ::backdrop oraz renderowaniem w warstwie najwyższej. Oszczędza około 200 linii kruchego JavaScriptu.
Po role="dialog" na <div> sięgaj tylko gdy:
- Obsługujesz przeglądarki starsze niż Chrome 37 / Firefox 98 / Safari 15.4 (mało prawdopodobne w 2026 r.).
- Projekt wymaga okna dialogowego, które nie może znajdować się w warstwie najwyższej (rzadkie).
- Naprawiasz niedostępne niestandardowe okno modalne podczas refaktoryzacji.
Każde okno dialogowe MUSI mieć dostępną nazwę (najsilniejszym wzorcem jest aria-labelledby wskazujące na widoczny nagłówek). Okna modalne wymagają też aria-modal="true".
Kontrakt klawiaturowy i fokus
Zgodnie z wzorcem APG dialog (modalny):
- Po otwarciu fokus przenosi się na pierwszy fokusowany element wewnątrz okna (często przycisk zamknięcia lub główne pole wejściowe).
- Tab i Shift+Tab przemieszczają fokus wyłącznie WEWNĄTRZ okna dialogowego — „pułapka fokusa”. Tab z ostatniego elementu wraca do pierwszego; Shift+Tab z pierwszego — do ostatniego.
- Escape zamyka okno dialogowe.
- Po zamknięciu fokus wraca do elementu, który otworzył okno. Zapisywanie i przywracanie fokusa jest obowiązkowe — użytkownicy, którzy tracą miejsce, nie mają punktu odniesienia.
- Reszta strony jest
inert(lubaria-hidden="true"plus niefokusowalna jako alternatywa) gdy okno jest otwarte.
Częste błędy
- Niestandardowe okno dialogowe bez pułapki fokusa. Tab wyskakuje z okna i ląduje za nim; użytkownicy tracą kontekst.
- Fokus nie wraca do wyzwalacza po zamknięciu. Kolejny Tab ląduje w treści dokumentu.
- Treść w tle pozostaje fokusowalna przez Tab, mimo że jest wizualnie ukryta za oknem dialogowym.
- Brak dostępnej nazwy. Okno otwiera się, a czytnik ekranu ogłasza jedynie „dialog”.
- Niestandardowe okno dialogowe bez
aria-modal="true"— technologie asystujące traktują je jako treść osadzoną. - Escape zamyka okno, ale jest ono renderowane przez portal, który traci fokus klawiaturowy podczas animacji zamknięcia.
Przykład
<!-- Zalecane -->
<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>
<!-- Gdy <dialog> jest niemożliwy -->
<div role="dialog" aria-modal="true" aria-labelledby="dlgTitle">
<h2 id="dlgTitle">Edit profile</h2>
…
</div>