Перейти до вмісту
Pandus

Доступне меню навігації

Оновлено 14 жовтня 2026 · 6 хв читання

Головна навігація — перше, чим користується кожен відвідувач, а в магазині вона часто розростається в мега-меню з категоріями, брендами та акціями. Найпоширеніша помилка доступності — не відсутній ARIA, а неправильний ARIA: role="menubar", скопійований з бібліотеки компонентів. Ця сторінка пояснює, що натомість радить APG. Вона входить до серії доступні UI-патерни.

В APG є патерн Menu і Menubar для меню застосунків — «списку варіантів, таких як дії чи функції», що поводиться як меню в настільному програмному забезпеченні. Його приклад навігаційного menubar містить прямо виражене застереження:

«Патерн menubar вимагає складної функціональності, зайвої для типової навігації сайту» … «Патерн, більш придатний для типової навігації сайту з розкривними групами посилань, — це патерн Disclosure.»

APG додає, що патерн disclosure «краще підходить для більшості вебсайтів, бо мало хто потребує додаткової функціональності клавіатури». Його приклад disclosure navigation не використовує роль menu, бо вона «не забезпечує складної функціональності, якої очікують допоміжні технології». role="menu" — це обіцянка поведінки меню в стилі настільних програм; якщо сайт її не виконує, таким меню користуватися важче, ніж звичайними посиланнями.

Рекомендація: орієнтир nav, вкладені списки посилань і кнопки disclosure для груп.

Відповідні критерії WCAG

Приклад коду

<nav aria-label="Головне меню">
  <ul>
    <li>
      <button type="button" aria-expanded="false" aria-controls="nav-women">Жінкам</button>
      <ul id="nav-women" hidden>
        <li><a href="/uk/women/dresses">Сукні</a></li>
        <li><a href="/uk/women/shoes" aria-current="page">Взуття</a></li>
      </ul>
    </li>
    <li><a href="/uk/sale">Розпродаж</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>

Примітки:

  • Якщо верхній пункт має бути ще й посиланням на сторінку категорії, в APG є варіант «Disclosure Navigation Menu with Top-Level Links»: посилання та окрема кнопка-перемикач стоять поруч. Не робіть один елемент одночасно посиланням і перемикачем.
  • Додайте Escape: закрийте відкриту групу й поверніть фокус на її кнопку, як у прикладі APG.
  • На мобільному кнопка-«гамбургер» — це той самий disclosure: aria-expanded, назва на кшталт «Меню», а панель іде за нею в DOM.

Взаємодія з клавіатури

З прикладу disclosure navigation APG:

Клавіша Функція
Tab / Shift + Tab Переміщує по кнопках і посиланнях верхнього рівня, а коли групу відкрито, — по її посиланнях
Enter або Space на кнопці Відкриває чи закриває групу
Enter на посиланні Переходить за посиланням
Escape Закриває відкриту групу й повертає фокус на її кнопку
Стрілки, Home, End Необов'язково: переміщують між кнопками й посиланнями; доповнюють Tab, а не замінюють його

Справжній menubar натомість вимагав би стрілок для переходу між пунктами, Tab для виходу з усього menubar і швидкого пошуку за першою літерою — це і є «складна функціональність», про яку йдеться в APG.

Типові помилки в інтернет-магазинах

  • Мега-меню, що відкриваються лише при наведенні миші; користувачі клавіатури проходять Tab по верхніх посиланнях і ніколи не дістаються підкатегорій.
  • role="menubar" і role="menuitem" на звичайних посиланнях, часто з теми чи плагіна, без поведінки стрілок.
  • Приховані підменю, що досі можуть отримати фокус: Tab зникає в невидимих посиланнях (фокус губиться за opacity: 0).
  • Назва категорії є і посиланням, і перемикачем, тож користувачі сенсорних екранів і клавіатури не можуть відкрити підменю.
  • Немає aria-expanded або він ніколи не змінюється з false.
  • Кілька орієнтирів nav без підписів (головний, футер, обліковий запис), тож користувачі програм зчитування з екрана не можуть їх розрізнити.
  • Кнопки-«гамбургери» без назви та мобільні меню, які не утримують і не повертають фокус, коли побудовані як накладка на весь екран.

Що знаходить автоматична перевірка, а що — ручне тестування

Автоматично (правило axe-core) Що знаходить
link-name, button-name Посилання меню та кнопки-перемикачі чи «гамбургери» без назви
aria-required-children, aria-required-parent menu/menubar без дочірніх menuitem, menuitem поза меню
aria-allowed-role Ролі, що не підходять елементові (порада)
aria-hidden-focus Посилання всередині підменю з aria-hidden, які досі можуть отримати фокус
list, listitem Зламана структура списку в навігації
landmark-unique Кілька навігаційних орієнтирів з однаковою назвою або без неї (порада)
bypass, skip-link Немає способу пропустити меню; посилання для пропуску зі зламаною ціллю
target-size Цілі меню, що надто малі

Усі вони є картками в нашій бібліотеці правил. Сканування бачить сторінку такою, якою вона завантажується, із закритими підменю. Ручне тестування: відкрийте кожну групу клавішами Enter чи Space, перевірте, що aria-expanded змінюється, натисніть Escape, пройдіть клавішею Tab відкритою групою, перевірте, що закриті групи не можуть отримати фокус, і повторіть з мобільним меню на ширині 320 CSS-пікселів. Розширення для браузера може перевірити сторінку з відкритою групою.

Запустіть безкоштовну перевірку однієї сторінки на головній. Це автоматична перевірка, а не повний аудит.

Часті запитання

Чи варто в навігації сайту використовувати role="menu" або role="menubar"?

Зазвичай ні. APG попереджає, що патерн menubar вимагає складної функціональності, зайвої для типової навігації сайту, і радить патерн disclosure для навігації з розкривними групами посилань.

Що таке disclosure navigation?

Елемент nav зі списком посилань, де кожна група з підпосиланнями має кнопку з aria-expanded, що показує чи приховує вкладений список. Користувачі переходять ним клавішами Tab, Enter і Space, як і рештою сторінки.

Як позначити поточну сторінку в меню?

Поставте aria-current="page" на посиланні на сторінку, де перебуває користувач, і покажіть це ще й візуально, а не лише кольором.

Чи має меню підтримувати клавіші-стрілки?

У патерні disclosure — ні. Приклад APG підтримує стрілки, Home та End як необов'язкове доповнення до Tab. Справжній menubar, навпаки, мусить реалізовувати повну модель керування стрілками.

Чи може автоматична перевірка протестувати меню навігації?

Вона знаходить посилання й кнопки без назв, ролі меню без пунктів меню, дубльовані непідписані навігаційні орієнтири та приховані, але доступні для фокуса посилання. Вона не може перевірити, чи підменю відкриваються з клавіатури і чи оновлюється aria-expanded.

Джерела

  • 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/