Focus trap
Wzorzec, który utrzymuje fokus klawiatury wewnątrz otwartego okna modalnego — zapobiega wyjściu Tab z powrotem do dokumentu i przywraca fokus do elementu wyzwalającego po zamknięciu okna.
Focus trap (pułapka focusu) to celowe ograniczenie nawigacji klawiaturowej: gdy otwarte jest okno modalne, klawisz Tab krąży wyłącznie między elementami aktywnymi wewnątrz tego okna. Shift+Tab działa w odwrotnym kierunku. Użytkownik nie może użyć Tab, by wrócić do (wizualnie zablokowanej) strony za modalem, dopóki go jawnie nie zamknie.
Utrzymywanie focusu jest wymagane w dostępnych oknach modalnych. Bez niego użytkownicy klawiatury i czytników ekranu trafiają na niewidoczną treść strony, której ani nie widzą, ani nie mogą opuścić.
Dlaczego to konieczne
Okno modalne jest wizualnie prezentowane jako warstwa nad stroną. Intencja jest jednoznaczna: użytkownik ma pracować z modalem, aż skończy, a następnie wrócić do strony. Dla użytkowników myszy jest to intuicyjne: kliknięcie poza modalem nic nie robi (lub go zamyka); kliknięcie wewnątrz dosięga kontrolek modalu.
Bez focus trap użytkownicy klawiatury otrzymują niespójne doświadczenie:
- Otwiera się modal. Fokus przenosi się (lub powinien się przenieść) do pierwszego aktywnego elementu wewnątrz.
- Użytkownik naciska Tab. Fokus przechodzi do kolejnego aktywnego elementu w modalu.
- Użytkownik dalej naciska Tab. Fokus osiąga w końcu ostatni aktywny element w modalu.
- Jeszcze jeden Tab. Bez pułapki fokus skacze do kolejnego aktywnego elementu w dokumencie — gdzieś za modalem, niewidocznego dla użytkownika.
Jedynym sygnałem, że tak się stało, jest zniknięcie wskaźnika focusu z modalu. Użytkownik nie ma pojęcia, gdzie jest jego fokus.
Pełny wzorzec dla modalu
Kompletny dostępny modal zawiera:
- Fokus przenosi się do modalu przy jego otwarciu — zazwyczaj do pierwszego aktywnego elementu lub do nagłówka modalu (jeśli nagłówek ma
tabindex="-1"dla programowego focusu). - Fokus jest uwięziony wewnątrz modalu: Tab od ostatniego elementu wraca do pierwszego; Shift+Tab od pierwszego wraca do ostatniego.
- Escape zamyka modal i przywraca fokus do elementu wyzwalającego, który go otworzył (nie do body dokumentu).
- Kliknięcie poza modalem zamyka go — zachowanie opcjonalne; nie każdy modal tak robi, ale jeśli twój to robi, fokus musi pozostać uwięziony podczas otwarcia.
role="dialog"wraz zaria-modal="true"na elemencie modalu, zaria-labelledbywskazującym na jego nagłówek.
Implementacje
Najczęściej cytowaną biblioteką jest focus-trap (npm: focus-trap, focus-trap-react, focus-trap-vue) — mała, bez zależności, obsługuje wszystkie przypadki brzegowe (pomija niewidoczne elementy, integruje się z inert, przywraca fokus przy zamknięciu).
Nowoczesnym prymitywem przeglądarki jest <dialog> z dialog.showModal(), który automatycznie utrzymuje fokus i obsługuje Escape. Wsparcie przeglądarek jest już wystarczająco szerokie, by używać tego jako linii bazowej.
Antywzorzec: „pułapka, która nie zwalnia”
Focus trap musi zwolnić fokus przy zamknięciu modalu. Najczęstszy błąd implementacyjny to zapomnienie o przywróceniu focusu do oryginalnego elementu wyzwalającego — fokus trafia wtedy na body dokumentu, co czytniki ekranu ogłaszają jako ciszę. Użytkownik zostaje „upuszczony w ciemność” i musi od nowa nawigować Tab od początku strony.