Dostępne menu nawigacyjne
Zaktualizowano 14 października 2026 · 6 min czytania
Główna nawigacja to pierwsza rzecz, z której korzysta każdy odwiedzający, a w sklepie często rozrasta się do mega-menu z kategoriami, markami i promocjami. Najczęstszym błędem dostępności nie jest brak ARIA, lecz zła ARIA: role="menubar" skopiowane z biblioteki komponentów. Ta strona wyjaśnia, co zamiast tego zaleca APG. Należy do serii dostępne wzorce interfejsu.
Menu czy disclosure? Co mówi APG
APG ma wzorzec Menu i Menubar dla menu aplikacji – „listy wyborów, takich jak akcje lub funkcje”, zachowującej się jak menu w oprogramowaniu desktopowym. Jego przykład menubar do nawigacji zawiera wyraźne ostrzeżenie:
„Wzorzec menubar wymaga złożonej funkcjonalności, niepotrzebnej w typowej nawigacji serwisu” … „Wzorcem lepiej dopasowanym do typowej nawigacji serwisu z rozwijanymi grupami linków jest wzorzec Disclosure.”
APG dodaje, że wzorzec disclosure „lepiej pasuje do większości serwisów, ponieważ niewiele z nich potrzebuje dodatkowej obsługi klawiatury”. Jego przykład nawigacji disclosure nie używa roli menu, ponieważ „nie zapewnia złożonej funkcjonalności, jakiej oczekują technologie wspomagające”. role="menu" to obietnica zachowania jak w menu desktopowym; jeśli serwis jej nie dotrzymuje, takie menu jest trudniejsze w użyciu niż zwykłe linki.
Zalecenie: landmark nav, zagnieżdżone listy linków i przyciski disclosure dla grup.
Kryteria WCAG
- 2.1.1 Klawiatura (A): każde podmenu otwiera się klawiaturą, a nie tylko po najechaniu myszą.
- 1.3.1 Informacje i relacje (A): listy i zagnieżdżenie przekazują hierarchię.
- 4.1.2 Nazwa, rola, wartość (A): przyciski przełączające udostępniają
aria-expanded. - 1.4.13 Treść spod kursora lub fokusu (AA): rozwijane panele otwierane po najechaniu można odrzucić (Escape) i da się na nie najechać.
- 2.4.1 Możliwość pominięcia bloków (A): link pomijający lub landmarki pozwalające ominąć długie menu.
- 2.4.3 Kolejność fokusu (A) i 2.4.7 Widoczny fokus (AA).
- 3.2.3 Spójna nawigacja (AA): ta sama kolejność na każdej stronie.
- 1.4.10 Dopasowanie do ekranu (AA) i 2.5.8 Rozmiar celu (minimum) (AA) dla menu mobilnego.
Przykład kodu
<nav aria-label="Główna">
<ul>
<li>
<button type="button" aria-expanded="false" aria-controls="nav-women">Kobiety</button>
<ul id="nav-women" hidden>
<li><a href="/pl/kobiety/sukienki">Sukienki</a></li>
<li><a href="/pl/kobiety/buty" aria-current="page">Buty</a></li>
</ul>
</li>
<li><a href="/pl/wyprzedaz">Wyprzedaż</a></li>
</ul>
</nav>
<script>
document.querySelectorAll('nav button[aria-expanded]').forEach((button) => {
const list = document.getElementById(button.getAttribute('aria-controls'));
button.addEventListener('click', () => {
const open = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!open));
list.hidden = open;
});
});
</script>
Uwagi:
- Jeśli pozycja najwyższego poziomu ma być także linkiem do strony kategorii, APG ma wariant „Disclosure Navigation Menu with Top-Level Links”: link i osobny przycisk przełączający stoją obok siebie. Nie należy robić z jednego elementu jednocześnie linku i przełącznika.
- Warto dodać Escape: zamknąć otwartą grupę i oddać fokus jej przyciskowi, jak w przykładzie APG.
- Na telefonie przycisk „hamburger” to to samo disclosure:
aria-expanded, nazwa taka jak „Menu” i panel następujący po nim w DOM.
Obsługa klawiaturą
Z przykładu nawigacji disclosure w APG:
| Klawisz | Funkcja |
|---|---|
| Tab / Shift + Tab | Przechodzi przez przyciski i linki najwyższego poziomu, a gdy grupa jest otwarta, także przez jej linki |
| Enter lub Spacja na przycisku | Otwiera lub zamyka grupę |
| Enter na linku | Otwiera link |
| Escape | Zamyka otwartą grupę i oddaje fokus jej przyciskowi |
| Strzałki, Home, End | Opcjonalnie: przechodzą między przyciskami i linkami; uzupełniają Tab, a go nie zastępują |
Prawdziwy menubar wymagałby natomiast strzałek do poruszania się między pozycjami, Tab do opuszczenia całego menubara i wyszukiwania po pierwszej literze – to właśnie „złożona funkcjonalność”, o której mówi APG.
Typowe błędy w sklepach internetowych
- Mega-menu otwierane wyłącznie po najechaniu myszą; użytkownicy klawiatury przechodzą Tabem po linkach najwyższego poziomu i nigdy nie docierają do podkategorii.
role="menubar"irole="menuitem"na zwykłych linkach, często z motywu lub wtyczki, bez obsługi strzałek.- Ukryte podmenu, które nadal przyjmują fokus: Tab znika w niewidocznych linkach (fokus gubi się za
opacity: 0). - Nazwa kategorii jest jednocześnie linkiem i przełącznikiem, więc użytkownicy ekranów dotykowych i klawiatury nie mogą otworzyć podmenu.
- Brak
aria-expandedalbo wartość, która nigdy nie zmienia się zfalse. - Kilka landmarków
navbez etykiet (główna, stopka, konto), więc użytkownicy czytników ekranu nie potrafią ich odróżnić. - Przyciski hamburger bez nazwy i menu mobilne zbudowane jako nakładka pełnoekranowa, które nie zatrzymują ani nie oddają fokusu.
Co wychwytuje kontrola automatyczna, a co wymaga testu ręcznego
| Automatycznie (reguła axe-core) | Co znajduje |
|---|---|
link-name, button-name |
Linki menu oraz przyciski przełączające lub hamburger bez nazwy |
aria-required-children, aria-required-parent |
menu/menubar bez elementów menuitem, menuitem poza menu |
aria-allowed-role |
Role niepasujące do elementu (wskazówka) |
aria-hidden-focus |
Linki w podmenu z aria-hidden, które nadal mogą przyjąć fokus |
list, listitem |
Uszkodzona struktura listy w nawigacji |
landmark-unique |
Kilka landmarków nawigacji o tej samej nazwie lub bez nazwy (wskazówka) |
bypass, skip-link |
Brak sposobu pominięcia menu; link pomijający z błędnym celem |
target-size |
Zbyt małe cele w menu |
Wszystkie to karty z naszej biblioteki reguł. Skan widzi stronę taką, jaka się ładuje, z zamkniętymi podmenu. Test ręczny: proszę otworzyć każdą grupę klawiszami Enter lub Spacja, sprawdzić, czy aria-expanded się zmienia, nacisnąć Escape, przejść Tabem przez otwartą grupę, sprawdzić, czy zamknięte grupy nie przyjmują fokusu, i powtórzyć to z menu mobilnym przy szerokości 320 pikseli CSS. Rozszerzenie do przeglądarki może sprawdzić stronę z otwartą grupą.
Darmowa kontrola jednej strony uruchomiona na stronie głównej to automatyczna kontrola, a nie pełny audyt.
Najczęstsze pytania
Czy nawigacja w serwisie powinna używać role="menu" lub role="menubar"?
Zwykle nie. APG ostrzega, że wzorzec menubar wymaga złożonej funkcjonalności, niepotrzebnej w typowej nawigacji serwisu, i zaleca wzorzec disclosure dla nawigacji z rozwijanymi grupami linków.
Co to jest nawigacja disclosure?
Element nav z listą linków, w którym każda grupa z podlinkami ma przycisk z aria-expanded pokazujący lub ukrywający podlistę. Użytkownicy poruszają się po niej klawiszami Tab, Enter i Spacja, tak jak po reszcie strony.
Jak oznaczyć bieżącą stronę w menu?
Na linku do strony, na której jest użytkownik, należy ustawić aria-current="page" i pokazać to także wizualnie, nie tylko kolorem.
Czy menu potrzebuje obsługi strzałek?
Nie we wzorcu disclosure. Przykład APG obsługuje strzałki, Home i End jako opcjonalny dodatek do Tab. Prawdziwy menubar natomiast musi zaimplementować pełny model strzałek.
Czy kontrola automatyczna przetestuje menu nawigacyjne?
Znajduje linki i przyciski bez nazw, role menu bez pozycji menu, zduplikowane nieopisane landmarki nawigacji oraz ukryte, ale przyjmujące fokus linki. Nie sprawdzi, czy podmenu otwierają się klawiaturą ani czy aria-expanded się aktualizuje.
Źródła
- W3C WAI, APG Navigation Menubar example (caution about site navigation): https://www.w3.org/WAI/ARIA/apg/patterns/menubar/examples/menubar-navigation/
- W3C WAI, APG Menu and Menubar pattern: https://www.w3.org/WAI/ARIA/apg/patterns/menubar/
- W3C WAI, APG Disclosure pattern: https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/
- W3C WAI, APG Disclosure Navigation Menu example: https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/
- W3C WAI, APG Menu Button pattern: https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/