Przejdź do treści
Pandus

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.

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

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" i role="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-expanded albo wartość, która nigdy nie zmienia się z false.
  • Kilka landmarków nav bez 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/