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

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

Мануэль Матузович
Manuel Matuzović

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

Для большинства веб-сайтов вам нужно создать что-то не слишком простое и не слишком сложное.

Строим слой за слоем

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

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

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

<a href="/home">Home</a>
<a href="/about-us">About us</a>
<a href="/pricing">Pricing</a>
<a href="/contact">Contact</a>
/* 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 (состояние) указывает элемент, который представляет текущий элемент в контейнере или наборе связанных элементов. Токен страницы, используемый для обозначения ссылки в наборе ссылок на страницы, где ссылка визуально оформлена так, чтобы представлять отображаемую в данный момент страницу. [Доступные многофункциональные интернет-приложения (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, в списке ссылки отображаются как связная группа элементов, а не просто куча ссылок.

Примечательная деталь VoiceOver в 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> , к которым может перейти программа чтения с экрана. Наличие ориентиров на странице может быть полезным, поскольку позволяет пользователям программ чтения с экрана получать доступ к важным областям страницы напрямую, без необходимости взаимодействия с остальной частью страницы. Например, вы можете переходить от ориентира к ориентиру, нажимая клавишу D в NVDA. В Voice Over вы можете использовать ротор, чтобы составить список всех ориентиров на странице, нажав VO + U.

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

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

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

На изображении показаны три достопримечательности, на каждой из которых написано «навигация».
Ротор в 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 в медиа-запрос с предпочтительным уменьшением движения, поскольку анимация может вызвать у некоторых пользователей тошноту, головокружение и головные боли .

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

Поддержка браузера

  • Хром: 86.
  • Край: 86.
  • Фаерфокс: 85.
  • Сафари: 15.4.

Источник

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

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

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

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

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

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

Если вы помните, как началась эта статья, с целью, чтобы решение «не было ни слишком простым, ни слишком сложным», вот где мы сейчас находимся. Однако можно перепроектировать навигацию.

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

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

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

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

навигация (роль) WAI-ARIA 1.1

Роль меню

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

меню (роль) WAI-ARIA 1.1

Роль меню

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

полоса меню (роль) WAI-ARIA 1.1

Роль пункта меню

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

пункт меню (роль) WAI-ARIA 1.1

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

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

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

<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 (APG) сюда входят:

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

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

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

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

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

Изображение героя Мика Хаупта