Obsługa klawiaturą w aplikacjach webowych – wygoda, dostępność i kontrola

desi9n.pl logo desi9n.pl

Mapa strony
PL EN

Klawiatura to podstawowe narzędzie dostępności — i źródło połowy problemów w audytach WCAG. Focus, tabindex, focus trap, skróty, semantyczny HTML — praktyczny przewodnik.

Użytkownik porusza się po aplikacji internetowej za pomocą klawiatury – zaznaczone aktywne elementy interfejsu
Ilustracja pokazująca nawigację po aplikacji internetowej wyłącznie za pomocą klawiatury – funkcja wspierająca dostępność i komfort pracy użytkownika.

Klawiatura to podstawowe narzędzie pracy — i dostępności

Większość osób kojarzy obsługę klawiaturą z wygodą i skrótami klawiszowymi. W praktyce to jednak coś więcej — dla użytkowników, którzy nie mogą korzystać z myszy (osoby z niepełnosprawnością ruchową, użytkownicy czytników ekranu, osoby pracujące z urządzeniami bez ekranu dotykowego), klawiatura jest jedynym sposobem nawigacji po aplikacji.

Standard WCAG 2.2, kryterium 2.1.1, mówi wprost: cała funkcjonalność musi być dostępna z klawiatury. To nie sugestia — to warunek spełnienia poziomu A. W audytach dostępności, które realizujemy, problemy z obsługą klawiaturą pojawiają się w ponad połowie badanych aplikacji.

Focus, tabindex i kolejność nawigacji

Nawigacja klawiaturą opiera się na mechanizmie focusa — podświetleniu aktywnego elementu podczas przechodzenia klawiszem Tab. Żeby to działało poprawnie, trzeba rozumieć trzy wartości atrybutu tabindex:

  • tabindex="0" — element uczestniczy w naturalnej kolejności tabulacji (zgodnie z pozycją w DOM). Używamy go, gdy chcemy dołączyć do nawigacji element, który domyślnie nie jest interaktywny.
  • tabindex="-1" — element jest pomijany w nawigacji Tab, ale można go sfocusować programowo (np. element.focus()). Przydatne przy modalnach i dynamicznych widokach.
  • tabindex="1" i wyżej — wymusza pierwszeństwo w nawigacji, ale w praktyce jest antywzorcem, bo łamie naturalną kolejność i utrudnia orientację.

Samo ustawienie tabindex to za mało. Trzeba jeszcze zadbać o widoczność focusa. Przeglądarka daje domyślny outline, ale wiele projektów go ukrywa (outline: none) ze względów estetycznych. Lepsze podejście to nadpisanie stylu focusa za pomocą :focus-visible:

button:focus-visible,
a:focus-visible { outline: 2px solid #1a73e8; outline-offset: 2px;
}

Pseudoklasa :focus-visible aktywuje się tylko przy nawigacji klawiaturą, nie przy kliknięciu myszą — dzięki temu nie irytuje użytkowników myszy, a jednocześnie wspiera tych, którzy potrzebują wskazówki wizualnej.

Semantyczny HTML kontra div z onclick

Elementy <a>, <button>, <input><select> są domyślnie focusowalne i reagują na klawiaturę — Enter aktywuje link i przycisk, spacja zaznacza checkbox. Problem pojawia się, gdy programiści używają <div> lub <span> z obsługą kliknięcia przez JavaScript:

<!-- Tak nie rób -->
<div onclick="zapisz()">Zapisz</div>
<!-- Użyj natywnego elementu -->
<button type="button" onclick="zapisz()">Zapisz</button>

Różnica wydaje się kosmetyczna, ale <div> nie jest focusowalny, nie reaguje na Enter ani spację i nie jest rozpoznawany przez czytniki ekranu jako element interaktywny. Żeby go „naprawić", trzeba dodać role="button", tabindex="0" i obsługę zdarzeń keydown — trzy linie kodu, które natywny <button> daje za darmo.

W praktyce widzę ten problem regularnie w aplikacjach budowanych na komponentach frameworków (React, Angular, Vue), gdzie stylowany <div> jest prostszy do zaimplementowania niż poprawnie ostylowany <button>. To zawsze dług technologiczny, który wraca przy pierwszym teście dostępności.

Skróty klawiaturowe — wygoda, ale z rozwagą

Skróty klawiaturowe przyspieszają pracę w aplikacjach profesjonalnych. Gmail, Jira, Slack, Figma — każde z tych narzędzi ma własny zestaw kombinacji. Problem zaczyna się, gdy skróty są nieintuicyjne, nieudokumentowane lub kolidują ze skrótami systemowymi.

Kilka realnych pułapek:

  • Gmail: klawisz E archiwizuje wiadomość. Jedno przypadkowe naciśnięcie — i mail znika z widoku. Użytkownik nie dostaje potwierdzenia.
  • Asana: Tab+T otwiera nowe zadanie. Kombinacja łatwa do przypadkowego wywołania podczas nawigacji tabulatorem.
  • Konflikty systemowe: Alt+F4 zamyka okno, Ctrl+W zamyka kartę — jeśli aplikacja przechwytuje te kombinacje, użytkownik traci kontrolę nad systemem.

Dobra praktyka to oferowanie widoku pomocy z listą skrótów (często ? lub Ctrl+/) i możliwości ich wyłączenia lub zmiany. WCAG 2.2, kryterium 2.1.4 (Character Key Shortcuts), wymaga, żeby skróty jednoznakowe dało się wyłączyć lub przemapować.

Modale, ESC i pułapka focusa

Okna modalne to jedno z najtrudniejszych miejsc w obsłudze klawiaturą. Poprawnie zaprojektowany modal powinien:

  • Przenieść focus na pierwszy interaktywny element po otwarciu.
  • Zamykać się po naciśnięciu Esc.
  • Wykonywać główną akcję po Enter (jeśli to dialog potwierdzenia).
  • Zapętlać focus w swoim obrębie — tzw. focus trap. Tab na ostatnim elemencie wraca do pierwszego, Shift+Tab na pierwszym — do ostatniego.

Bez focus trap użytkownik klawiatury może „uciec" z modala w tło strony, nie widząc ani treści modala, ani kontekstu strony. To jedna z najczęstszych barier, którą spotykamy podczas testów dostępności.

Nowoczesne przeglądarki wspierają natywny element <dialog> z wbudowanym zarządzaniem focusa i obsługą Esc. Jeśli piszesz modalne od zera w React czy Vue, warto sięgnąć po biblioteki takie jak HeadlessUI lub Radix, które implementują ARIA poprawnie.

Backspace, historia nawigacji i formularze

Klawisz Backspace w przeglądarkach przez lata cofał użytkownika na poprzednią stronę. To było źródło frustracji — ktoś wypełniał formularz, przypadkiem kliknął Backspace poza polem tekstowym i tracił wszystkie dane. Chrome od wersji 52 (2016) wyłączył to zachowanie. Firefox nadal je wspiera w domyślnej konfiguracji.

Niezależnie od przeglądarki, dobrą praktyką w aplikacjach z formularzami jest:

  • Przechwytywanie zdarzenia beforeunload, żeby ostrzec użytkownika przed utratą danych.
  • Zapisywanie stanu formularza w sessionStorage lub stanie aplikacji, żeby dało się go odzyskać.
  • Unikanie przechwytywania Backspace globalnie — użytkownik oczekuje, że ten klawisz kasuje znaki w polu tekstowym.

Powiadomienia — toast to nie potwierdzenie

Wiele aplikacji zastąpiło klasyczne dialogi potwierdzenia krótkimi toastami (dymkami informacyjnymi, które znikają po kilku sekundach). To wygodne dla szybkich operacji, ale niebezpieczne przy akcjach nieodwracalnych.

Toast, który znika po 3 sekundach, może nie zostać przeczytany przez osobę korzystającą z czytnika ekranu — chyba że ma atrybut role="status" lub aria-live="polite". Trwałe akcje (usunięcie konta, wysłanie wiadomości, zatwierdzenie płatności) powinny wymagać jawnego potwierdzenia z focusem na przyciskach Tak/Nie.

Checklist — co sprawdzić w swojej aplikacji

  1. Czy da się przejść przez całą aplikację samym Tabem? Sprawdź formularz, menu, modal, nawigację.
  2. Czy focus jest zawsze widoczny? Wyłącz mysz i przejdź przez stronę — jeśli nie wiesz, gdzie jesteś, użytkownik klawiatury też nie wie.
  3. Czy modalne mają focus trap i zamykają się po Esc?
  4. Czy skróty klawiaturowe są udokumentowane i da się je wyłączyć?
  5. Czy elementy interaktywne to natywne <button><a>, a nie <div> z onclick?
  6. Czy toasty z informacją o błędzie/sukcesie mają aria-live?

Obsługa klawiaturą to jeden z fundamentów tworzenia aplikacji webowych. Nie wymaga dużych nakładów, ale wymaga świadomości. Jeśli chcesz sprawdzić, jak Twoja aplikacja radzi sobie z nawigacją klawiaturą — skontaktuj się z nami.

Źródła

Tagi artykułu:

Czy podobał Ci się ten artykuł? Szukasz partnera, który pomoże Ci w realizacji nowoczesnych rozwiązań? Jeśli chcesz wdrożyć omawiane rozwiązania w swoim projekcie, skontaktuj się z nami i rozpocznijmy współpracę!

Kontakt