Standardy · ARIA

Rola Okno

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 (lub aria-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>