Создание основной навигации для сайта

В этом руководстве описывается, как создать доступную основную навигацию сайта. Вы узнаете о семантическом HTML, специальных возможностях и о том, как использование атрибутов ARIA иногда может принести больше вреда, чем пользы.

Manuel Matuzović
Manuel Matuzović

Существует множество способов создания основной навигации сайта с точки зрения стиля, функциональности, а также базовой разметки и семантической информации. Если реализация слишком минималистична, она подходит большинству людей, но пользовательский опыт (UX) может быть не очень хорошим. Если он слишком сложный, это может запутать пользователей или даже помешать им получить к нему доступ.

Для большинства сайтов лучше всего подходит средний вариант.

Послойное построение

В этом руководстве мы начнем с базовой настройки и будем добавлять функции слой за слоем, пока не получим карту, которая будет содержать достаточно информации, стилей и функций, чтобы удовлетворить большинство пользователей. Для этого вы используете принцип прогрессивного улучшения, который гласит, что вы начинаете с самого фундаментального и надежного решения и постепенно добавляете уровни функциональности. Если один из уровней по какой-то причине не работает, навигация все равно будет работать, поскольку она плавно возвращается к базовому уровню.

Базовая структура

Для создания базовой навигации вам понадобятся две вещи: элементы <a> и несколько строк CSS, чтобы улучшить стиль и макет ссылок по умолчанию.

  • HTML

    <a href="/home">Home</a>
    <a href="/about-us">About us</a>
    <a href="/pricing">Pricing</a>
    <a href="/contact">Contact</a>
    
  • CSS

    /* Define variables for your colors */
    :root {
      --color-shades-dark: rgb(25, 25, 25);
    }
    
    /* Use the alternative box model
    Details: <https://web.dev/learn/css/box-model/> */
    *{
      box-sizing: border-box;
    }
    
    /* Basic font styling */
    body {
      font-family: Segoe UI, system-ui, -apple-system, sans-serif;
      font-size: 1.6rem;
    }
    
    /* Link styling */
    a {
      --text-color: var(--color-shades-dark);
      border-block-end: 3px solid var(--border-color, transparent);
      color: var(--text-color);
      display: inline-block;
      margin-block-end: 0.5rem; /* See note at the bottom of this chapter */
      margin-inline-end: 0.5rem;
      padding: 0.1rem;
      text-decoration: none;
    }
    
    /* Change the border-color on :hover and :focus */
    a:where(:hover, :focus) {
      --border-color: var(--text-color);
    }
    
Посмотрите шаг 1 "Базовый код HTML и CSS" на CodePen.

Это удобно для большинства пользователей, независимо от того, как они заходят на сайт. Навигация доступна с помощью мыши, клавиатуры, сенсорного устройства или программы чтения с экрана, но есть возможности для улучшения. Вы можете улучшить этот базовый шаблон, добавив дополнительные функции и информацию.

Вот как это можно сделать:

  • Выделять активную страницу.
  • Сообщать пользователям программ чтения с экрана о количестве элементов.
  • Добавьте ориентир, чтобы пользователи программы чтения с экрана могли переходить к навигации с помощью быстрого клавиш.
  • Скрывать навигацию на узких экранах.
  • Улучшите стиль фокуса.

Выделять активную страницу

Чтобы выделить активную страницу, можно добавить класс к соответствующей ссылке.

<a href="/about-us" class="active-page">About us</a>

Проблема такого подхода в том, что информация о том, какая ссылка активна, передается только визуально. Незрячий пользователь программы чтения с экрана не сможет отличить активную страницу от других. К счастью, стандарт Accessible Rich Internet Applications (ARIA) позволяет передавать эту информацию семантически. Используйте атрибут и значение aria-current="page" вместо класса.

aria-current (состояние) указывает на элемент, который представляет текущий объект в контейнере или наборе связанных элементов. Токен страницы, который используется для обозначения ссылки в наборе ссылок для разбивки на страницы. Ссылка визуально оформлена так, чтобы представлять текущую страницу. [Accessible Rich Internet Applications (WAI-ARIA) 1.1](https://www.w3.org/TR/wai-aria/#aria-current)

С дополнительным атрибутом программа чтения с экрана теперь объявляет что-то вроде "текущая страница, ссылка, О нас" вместо просто "ссылка, О нас".

<a href="/about-us" aria-current="page" class="active-page">About us</a>

Удобный побочный эффект заключается в том, что вы можете использовать атрибут для выбора активной ссылки в CSS, что делает класс active-page устаревшим.

<a href="/home">Home</a>
<a href="/about-us" aria-current="page">About us</a>
<a href="/pricing">Pricing</a>
<a href="/contact">Contact</a>
/* Change border-color and color for the active page */
[aria-current="page"] {
  --border-color: var(--color-highlight);
  --text-color: var(--color-highlight);
}
Посмотрите шаг 2: выделение активной страницы на CodePen.

Озвучивать количество объектов

Посмотрев на навигацию, зрячие пользователи могут сказать, что она содержит только четыре ссылки. Незрячий пользователь программы чтения с экрана не может получить эту информацию так же быстро. Возможно, им придется просмотреть весь список ссылок. Если список короткий, как в этом примере, это не проблема, но если в нем 40 ссылок, задача может оказаться сложной. Если пользователь программы чтения с экрана заранее знает, что в меню навигации много ссылок, он может выбрать другой, более эффективный способ навигации, например поиск по сайту.
Чтобы сообщить пользователю о количестве элементов, можно поместить каждую ссылку в элемент списка (<li>), вложенный в маркированный список (<ul>).

<ul>
  <li>
     <a href="/home">Home</a>
  </li>
  <li>
    <a href="/about-us" aria-current="page">About us</a>
  </li>
  <li>
    <a href="/pricing">Pricing</a>
  </li>
  <li>
    <a href="/contact">Contact</a>
  </li>
</ul>

Когда пользователь программы чтения с экрана находит список, программа сообщает ему что-то вроде "список, 4 элемента".

Ниже показано, как работает навигация в программе чтения с экрана NVDA в Windows.

Теперь вам нужно адаптировать стиль, чтобы он выглядел как раньше.

/* Remove the default list styling and create a flexible layout for the list */
ul {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Basic link styling */
a {
  --text-color: var(--color-shades-dark);

  border-block-end: 3px solid var(--border-color, transparent);
  color: var(--text-color);
  padding: 0.1rem;
  text-decoration: none;
}

Использование списков дает пользователям программ чтения с экрана следующие преимущества:

  • Пользователь может узнать общее количество элементов, прежде чем взаимодействовать с ними.
  • Для перехода от одного пункта списка к другому можно использовать быстрые клавиши.
  • Для перехода между списками можно использовать быстрые клавиши.
  • Программа чтения с экрана может озвучить индекс текущего элемента (например, "элемент списка, два из четырех").

Кроме того, если страница представлена без CSS, список показывает ссылки как связную группу элементов, а не просто как набор ссылок.

Примечательно, что в Safari вы потеряете все эти преимущества, если установите list-style: none. Это сделано намеренно. Команда WebKit решила удалить семантику списка, когда список не выглядит как список. В зависимости от сложности навигации это может быть проблемой. С одной стороны, навигация по-прежнему работает, и проблема затрагивает только VoiceOver в Safari. VoiceOver в сочетании с Chrome или Firefox, а также другие программы чтения с экрана, например NVDA, по-прежнему озвучивают количество элементов. С другой стороны, семантическая информация может быть очень полезна в некоторых ситуациях. Чтобы принять это решение, вам следует протестировать навигацию с реальными пользователями программ чтения с экрана и получить их отзывы. Если вы хотите, чтобы VoiceOver в Safari работал так же, как и другие программы чтения с экрана, вы можете задать роль списка ARIA в элементе <ul>. Это вернет поведение к состоянию до удаления стиля списка. Визуально список выглядит так же.

<ul role="list">
  <li>
     <a href="/home">Home</a>
  </li>
  ...
</ul>
Посмотрите шаг 3: озвучивание количества элементов на CodePen.

Добавить ориентир

Вы приложили совсем немного усилий, но значительно улучшили доступность сайта для пользователей программ чтения с экрана. Однако можно сделать ещё кое-что. С точки зрения семантики навигация по-прежнему представляет собой просто список ссылок, и трудно понять, что этот конкретный список является основным меню навигации вашего сайта. Чтобы превратить обычный список в навигационный, заключите элемент <ul> в элемент <nav>.

У элемента <nav> есть несколько преимуществ. В частности, программа чтения с экрана объявляет что-то вроде "навигация", когда пользователь взаимодействует с ней, и добавляет на страницу ориентир. Ориентиры – это специальные области на странице, например <header>, <footer> или <main>, к которым может переходить программа чтения с экрана. Ориентиры на странице могут быть полезны, поскольку они позволяют пользователям программ чтения с экрана напрямую получать доступ к важным областям на странице, не взаимодействуя с остальной частью страницы. Например, в NVDA можно переходить от одной метки к другой, нажимая клавишу D. В VoiceOver можно использовать ротор, чтобы посмотреть список всех ориентиров на странице. Для этого нажмите VO + U.

Список из четырех ориентиров: баннер, навигация, основная область, информация о контенте.
Ротор в VoiceOver, показывающий все ориентиры на странице.

В этом списке вы увидите четыре ориентира: баннер (элемент <header>), навигация (элемент <nav>), основной (элемент <main>) и информация о контенте (элемент <footer>). Этот список не должен быть слишком длинным, вам действительно нужно пометить только критические части вашего пользовательского интерфейса как ориентиры, такие как поиск по сайту, локальная навигация или разбивка на страницы.

Если на странице есть навигация на всех страницах сайта, локальная навигация по странице и разбивка на страницы, то на ней может быть три элемента <nav>. Это нормально, но теперь у нас есть три ориентира навигации, и семантически они все выглядят одинаково. Их сложно отличить друг от друга, если вы не знаете структуру страницы очень хорошо.

Изображение, на котором показаны три ориентира с надписью &quot;Навигация&quot;.
Ротор в VoiceOver, в котором перечислены три неразмеченных ориентира навигации.

Чтобы их можно было различить, добавьте к ним ярлыки с помощью aria-labelledby или aria-label.

<nav aria-label="Main">
    <ul>
      <li>
         <a href="/home">Home</a>
      </li>
      ...
  </ul>
</nav>
...
<nav aria-label="Select page">
    <ul>
      <li>
         <a href="/page-1">1</a>
      </li>
      ...
    </ul>
</nav>

Если выбранный вами ярлык уже существует на странице, вы можете использовать aria-labelledby и ссылаться на существующий ярлык с помощью атрибута id.

<nav aria-labelledby="pagination_heading">
  <h2 id="pagination_heading">Select a page</h2>
  <ul>
    <li>
       <a href="/page-1">1</a>
    </li>
    ...
  </ul>
</nav>

Достаточно краткого ярлыка, не будьте слишком многословны. Не используйте такие слова, как "навигация" или "меню", поскольку программа чтения с экрана уже сообщает пользователям эту информацию.

Ориентиры
VoiceOver перечисляет ориентиры: "баннер", "основная навигация", "основной", "навигация по страницам", "выбрать навигацию по страницам" и "информация о контенте".
Посмотрите шаг 4: добавление ориентира на CodePen.

Скрывать навигацию на узких экранах

Лично мне не нравится скрывать основную навигацию на узких экранах, но если список ссылок слишком длинный, без этого не обойтись. В этом случае вместо списка пользователи видят кнопку "Меню", значок меню или и то, и другое. Нажатие на кнопку показывает и скрывает список. Если вы знаете основы JavaScript и CSS, это выполнимая задача, но вам нужно позаботиться о нескольких вещах с точки зрения UX и доступности.

  • Скрыть список нужно так, чтобы он оставался доступным.
  • Навигация должна быть доступна с клавиатуры.
  • Навигация должна сообщать, видна ли она.

Добавление кнопки-бургера

Поскольку вы следуете принципу прогрессивного улучшения, вам нужно убедиться, что навигация по-прежнему работает и имеет смысл даже при отключенном JavaScript.
Первое, что нужно для навигации, – это кнопка-бургер. Вы создаете его в HTML в элементе шаблона, клонируете в JavaScript и добавляете в навигацию.

Страница с кнопкой-гамбургером.
Результат: на узких экранах вместо ссылок в навигации показывается кнопка-гамбургер.
<nav id="mainnav">
  ...
</nav>

<template id="burger-template">
  <button type="button" aria-expanded="false" aria-label="Menu" aria-controls="mainnav">
    <svg width="24" height="24" aria-hidden="true">
      <path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z">
    </svg>
  </button>
</template>
  1. Атрибут aria-expanded сообщает программе чтения с экрана, развернут ли элемент, которым управляет кнопка.
  2. aria-label дает кнопке так называемое доступное название, текстовую альтернативу значку бургера.
  3. Вы скрываете <svg> от технологий специальных возможностей с помощью aria-hidden, потому что у него уже есть текстовая метка, предоставленная aria-label.
  4. aria-controls сообщает технологии специальных возможностей, которая поддерживает этот атрибут (например, JAWS), каким элементом управляет кнопка.
const nav = document.querySelector('#mainnav')
const list = nav.querySelector('ul');
const burgerClone = document.querySelector('#burger-template').content.cloneNode(true);
const button = burgerClone.querySelector('button');

// Toggle aria-expanded attribute
button.addEventListener('click', e => {
  // aria-expanded="true" signals that the menu is currently open
  const isOpen = button.getAttribute('aria-expanded') === "true"
  button.setAttribute('aria-expanded', !isOpen);
});

// Hide list on keydown Escape
nav.addEventListener('keyup', e => {
  if (e.code === 'Escape') {
    button.setAttribute('aria-expanded', false);
  }
});

// Add the button to the page
nav.insertBefore(burgerClone, list);
  1. Пользователям удобно иметь возможность закрыть навигацию в любой момент, например, нажав клавишу Escape.
  2. Важно использовать insertBefore вместо appendChild, потому что кнопка должна быть первым элементом в навигации. Если пользователь клавиатуры или программы чтения с экрана нажмет Tab после нажатия кнопки, он ожидает, что фокус будет установлен на первом элементе списка. Если кнопка находится после списка, то это не так.

Затем вы сбрасываете стиль кнопки по умолчанию и делаете так, чтобы она была видна только в узких окнах просмотра.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
  }
}

/* Reset button styling */
button {
  all: unset;
  display: var(--nav-button-display, flex);
}
Посмотрите шаг 5: добавление кнопки-гамбургера на CodePen.

Скрыть список

Прежде чем скрыть список, расположите и стилизуйте навигацию и список так, чтобы макет был оптимизирован для узких областей просмотра, но при этом хорошо выглядел на больших экранах.
Сначала удалите <nav> из естественного потока страницы и поместите его в верхний угол области просмотра.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }
}

nav {
  position: var(--nav-position, fixed);
  inset-block-start: 1rem;
  inset-inline-end: 1rem;
}

Затем измените макет для узких областей просмотра, добавив новое пользовательское свойство (—-nav-list-layout). По умолчанию макет представляет собой столбец и переключается на строку на больших экранах.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }

  ul {
    --nav-list-layout: row;
  }
}

ul {
  display: flex;
  flex-direction: var(--nav-list-layout, column);
  flex-wrap: wrap;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

На узких экранах навигация должна выглядеть примерно так.

Страница со списком навигации и кнопкой меню.
Кнопка-гамбургер и список размещены в верхнем углу области просмотра.

Очевидно, что для списка нужен CSS. Переместим его в верхний угол, растянем по вертикали на весь экран, применим background-color и box-shadow.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }
  
  ul {
    --nav-list-layout: row;
    --nav-list-position: static;
    --nav-list-padding: 0;
    --nav-list-height: auto;
    --nav-list-width: 100%;
    --nav-list-shadow: none;
  }
}

ul {
  background: rgb(255, 255, 255);
  box-shadow: var(--nav-list-shadow, -5px 0 11px 0 rgb(0 0 0 / 0.2));
  display: flex;
  flex-direction: var(--nav-list-layout, column);
  flex-wrap: wrap;
  gap: 1rem;
  height: var(--nav-list-height, 100vh);
  list-style: none;
  margin: 0;
  padding: var(--nav-list-padding, 2rem);
  position: var(--nav-list-position, fixed);
  inset-block-start: 0; /* Logical property. Equivalent to top: 0; */
  inset-inline-end: 0; /* Logical property. Equivalent to right: 0; */
  width: var(--nav-list-width, min(22rem, 100vw));
}

button {
  all: unset;
  display: var(--nav-button-display, flex);
  position: relative;
  z-index: 1;
}

Список должен выглядеть примерно так на узких окнах просмотра, больше похож на боковую панель, чем на простой список.

Откроется список навигации.

Наконец, скройте список. Он должен появляться, когда пользователь нажимает кнопку, и исчезать при повторном нажатии. Важно скрыть только список, а не всю навигацию, потому что скрытие навигации также будет означать скрытие важного ориентира.

Ранее вы добавили событие клика для кнопки, чтобы переключать значение атрибута aria-expanded. Эту информацию можно использовать в качестве условия для показа и скрытия списка в CSS.

@media (min-width: 48em) {
  ul {
    --nav-list-visibility: visible;
  }
}

ul {
  visibility: var(--nav-list-visibility, visible);
}

/* Hide the list on narrow viewports, if it comes after an element with
   aria-expanded set to "false". */
[aria-expanded="false"] + ul {
  visibility: var(--nav-list-visibility, hidden);
}

Чтобы скрыть список, важно использовать объявление свойства, например visibility: hidden или display: none, а не opacity: 0 или translateX(100%). Эти свойства гарантируют, что ссылки не будут доступны для фокуса, когда навигация скрыта. Если использовать opacity или translate, контент будет удален визуально, поэтому ссылки будут невидимы, но по-прежнему доступны с помощью клавиатуры, что может запутать и расстроить пользователя. Если вы используете visibility или display, то контент будет скрыт визуально и станет недоступен для всех пользователей.

См. Шаг 6. Скрытие списка.

Анимация списка

Если вы не знаете, почему лучше использовать visibility: hidden;, а не display: none;, то это потому, что вы можете анимировать видимость. У него есть только два состояния: hidden и visible. Но его можно комбинировать с другими свойствами, например transform или opacity, чтобы создать эффект скольжения или появления. Это не сработает с display: none, потому что свойство display не анимируется.

Следующий код CSS создает эффект плавного появления и исчезновения элемента opacity.

ul {
  transition: opacity 0.6s linear, visibility 0.3s linear;
  visibility: var(--nav-list-visibility, visible);
}

[aria-expanded="false"] + ul {
  opacity: 0;
  visibility: var(--nav-list-visibility, hidden);
}

Если вы хотите анимировать движение, рекомендуем обернуть свойство transition в медиазапрос prefers-reduced-motion, поскольку анимация может вызывать у некоторых пользователей тошноту, головокружение и головную боль.

ul {
  visibility: var(--nav-list-visibility, visible);
}

@media (prefers-reduced-motion: no-preference) {
  ul {
    transition: transform 0.6s cubic-bezier(.68,-0.55,.27,1.55), visibility 0.3s linear;
  }
}

[aria-expanded="false"] + ul {
  transform: var(--nav-list-transform, translateX(100%));
  visibility: var(--nav-list-visibility, hidden);
}

Это гарантирует, что анимацию увидят только те пользователи, которые не предпочитают уменьшение движения.

Посмотрите шаг 7: анимация списка в CodePen.

Улучшите стиль фокуса

Пользователи, которые работают с клавиатурой, ориентируются на стили фокуса элементов при навигации по странице. Стандартные стили фокуса лучше, чем их отсутствие (что происходит, если вы задаете outline: none), но более четко видимые пользовательские стили фокуса улучшают пользовательский опыт.

Вот как выглядят стили фокуса по умолчанию для ссылки в Chrome 103.

Синий контур толщиной 2 пикселя вокруг ссылки в фокусе в Chrome 103.

Вы можете улучшить их, задав собственные стили и цвета. Используя :focus-visible вместо :focus, вы позволяете браузеру решать, когда уместно показывать стили фокуса. Стили :focus будут видны всем пользователям, независимо от того, используют ли они мышь, клавиатуру или сенсорный экран и нужны ли им эти стили. При использовании :focus-visible браузер применяет внутреннюю эвристику, чтобы решить, показывать ли их только пользователям клавиатуры или всем.

/* Remove the default :focus outline */
*:focus {
  outline: none;
}

/* Show a custom outline on :focus-visible */
*:focus-visible {
  outline: 2px solid var(--color-shades-dark);
  outline-offset: 4px;
}

Поддержка браузеров для :focus-visible

Browser Support

  • Chrome: 86.
  • Edge: 86.
  • Firefox: 85.
  • Safari: 15.4.

Source

Четко видимый темный контур толщиной 2 пикселя с отступом внутри.

Выделять объекты в фокусе можно по-разному. Рекомендуется использовать свойство outline, поскольку оно не нарушает макет, как это может произойти при использовании border, и хорошо работает с режимом высокой контрастности в Windows. Не рекомендуется использовать свойства background-color и box-shadow, поскольку при пользовательских настройках контрастности они могут не отображаться.

Сайт с темным фоном, на котором фокус выделен фиолетовым цветом.
Посмотрите шаг 8 "Улучшите стили фокуса" на CodePen.

Поздравляем! Вы создали семантически насыщенную, доступную и оптимизированную для мобильных устройств основную навигацию с прогрессивным улучшением.

Всегда есть что улучшить, например:

В начале статьи мы говорили, что решение должно быть "не слишком простым и не слишком сложным". Именно к этому мы и пришли. Однако навигацию можно усложнить.

Между навигацией и меню есть явное различие. Навигация – это набор ссылок для перехода между связанными документами. Меню – это набор действий, которые можно выполнить в документе. Иногда эти задачи пересекаются. Например, в меню навигации может быть кнопка, которая выполняет действие, например открывает модальное окно, или в меню может быть действие, которое переходит на другую страницу, например страницу в Справочном центре. В таких случаях важно не смешивать роли ARIA, а определить основное назначение компонента и выбрать соответствующую разметку и роли.

Элемент <nav> имеет неявную роль ARIA navigation, которой достаточно, чтобы сообщить, что элемент является навигацией, но часто на сайтах также используются menu, menubar и menuitem. Поскольку мы иногда используем эти термины как взаимозаменяемые, мы подумали, что их объединение для улучшения работы с программами чтения с экрана может иметь смысл. Прежде чем мы узнаем, почему это обычно не так, давайте взглянем на официальное определение этих ролей.

Роль навигации

Набор навигационных элементов (обычно ссылок) для перемещения по документу или связанным документам.

navigation (role) WAI-ARIA 1.1

Роль меню

Меню часто представляет собой список распространенных действий или функций, которые может вызвать пользователь. Роль menu подходит, когда список пунктов меню представлен так же, как в компьютерном приложении.

menu (роль) WAI-ARIA 1.1

Роль menubar

Представление меню, которое обычно остается видимым и обычно представлено горизонтально. Роль menubar используется для создания строки меню, аналогичной тем, которые используются в приложениях для Windows, Mac и Gnome. Строка меню используется для создания согласованного набора часто используемых команд. Авторы должны обеспечить, чтобы взаимодействие со строкой меню было аналогично типичному взаимодействию со строкой меню в графическом интерфейсе пользователя на компьютере.

menubar (role) WAI-ARIA 1.1

Роль menuitem

Вариант в наборе вариантов, содержащихся в меню или строке меню.

menuitem (роль) WAI-ARIA 1.1

В спецификации четко указано, что навигация используется для перемещения по документу или связанным документам, а меню – только для списка действий или функций, аналогичных меню в настольных приложениях. Если вы не создаете аналог Google Документов, то, скорее всего, вам не нужны роли меню для основной навигации.

Когда меню уместно?

Основное назначение пунктов меню – не навигация, а выполнение действий. Предположим, у вас есть список или таблица данных, и пользователи могут выполнять определенные действия с каждым элементом в списке. Вы можете добавить кнопку в каждую строку и показывать действия, когда пользователи нажимают на нее.

<ul>
  <li>
    Product 1

    <button aria-expanded="false" aria-controls="options1">Edit</button>

    <div role="menu" id="options1">
      <button role="menuitem">
        Duplicate
      </button>
      <button role="menuitem">
        Delete
      </button>
      <button role="menuitem">
        Disable
      </button>
    </div>
  </li>
  <li>
    Product 2
    ...
  </li>
</ul>

Последствия использования ролей меню

Очень важно использовать эти роли меню с умом, потому что многое может пойти не так.

Для меню требуется определенная структура DOM. Элемент menuitem должен быть прямым дочерним элементом menu. Следующий код может нарушить семантическое поведение:

 <!-- Wrong, don't do this -->
<ul role="menu">
  <li>
    <a href="#" role="menuitem">Item 1</a>
  </li>
</ul>

Опытные пользователи ожидают, что определенные сочетания клавиш будут работать с меню и строками меню. Согласно руководству по созданию ARIA-разметки, к ним относятся:

  • Ввод и Пробел – выбор пунктов меню.
  • Клавиши со стрелками во всех направлениях – для перехода между элементами.
  • Клавиши Home и End позволяют перейти к первому или последнему элементу соответственно.
  • A–Z – переместить фокус на следующий пункт меню, название которого начинается с введенного символа.
  • Esc – закрыть меню.

Если программа чтения с экрана обнаружит меню, она может автоматически изменить режим просмотра, чтобы вы могли использовать перечисленные выше сочетания клавиш. Неопытные пользователи программ чтения с экрана могут не знать, как работать с меню, потому что им неизвестны эти сочетания клавиш или они не умеют ими пользоваться.

То же самое относится к пользователям клавиатуры, которые могут ожидать, что они могут использовать Shift и Shift + Tab.

При создании меню и строк меню необходимо учитывать множество факторов, в первую очередь целесообразность их использования. При создании обычного сайта вам понадобится только элемент nav со списком и ссылками. Это также относится к одностраничным приложениям (SPA) или веб-приложениям. Используемый стек не имеет значения. Если вы не создаете что-то очень похожее на компьютерное приложение, избегайте ролей меню.

Дополнительные ресурсы