TGViewer
<divelopers> <divelopers> @alexnozer_dev · 1.18K subscribers
Post #63 488
Про меню

Что такое меню в пользовательских интерфейсах? Набор горизонтальных ссылок в шапке сайта — меню. Вертикальный набор ссылок, переключающих экраны в мобильном приложении — меню. Список действий над файлом в верхней части приложения (например, File -> Save As...) — меню. Раскрывающийся при нажатии на иконку-бургер список категорий товаров в магазине — меню.

В спецификации ARIA есть роли menu и menubar, а в спецификации WHATWG есть элемент <menu>. Есть большой соблазн использовать их не по назначению. Периодически я встречаю такое. Давайте разбираться.

Согласно спецификации, menu и menubar — это виджеты, которые предлагают список действий или функций, которые пользователь может вызвать. Эта роль уместна для меню, которые похожи на меню в десктопных приложениях. Что особенного в меню десктопных приложений? Дело в том, что в таких приложениях нет понятия "страница" и "URL-адрес". Пункты меню в десктопных приложениях выполняют какие-то действия, но не меняют URL.

Вспомните любое десктопное приложение, например Photoshop, Figma, VSCode, Word, Paint. У всех них в верхней части есть горизонтальное меню — это menubar. При нажатии пункта в этих меню происходит действие — открытие выпадающего вертикального меню — это и есть menu. Разница между menubar и menu в значении aria-orientation по умолчанию: horizontal для menubar и vertical для menu. Пользователи ожидают от menu и menubar возможности навигации между пунктами при помощи клавиш со стрелками, Home и End. От menu ожидается навигация стрелками вверх/вниз, а от menubar — влево/вправо.

Согласно той же спецификации, внутри menu и menubar могут располагаться только элементы с ролями menuitem, menuitemcheckbox и menuitemradio. Также элементы можно группировать при помощи роли group и разделять при помощи separator (в ARIA 1.3).

А вот типичный блок с ссылками на сайте не является меню в контексте спецификации. Об этом пишут и в ARIA практиках. Набор ссылок на сайте — это навигация. Поэтому паттерн меню в таком случае не применим. Навигация — это про страницы, URL-адреса и фрагменты (якори). Меню — это про вызов действий в приложении. Это очень похоже на вопрос "кнопка или ссылка".

Так вот: если при нажатии на элемент происходит переход на другую страницу (или перерисовка с изменением URL в SPA), переход к разделу на странице (якорь), страницу можно открыть в новой вкладке, новом окне, в инкогнито, ссылку можно скопировать, сохранить в закладки, поделиться, ссылка должна индексироваться — это навигация. Для этого нужно использовать элементы с ролями navigation и link, то есть встроенные элементы <nav> и <a>. Можно добавить список, если элементов больше 3-4.

<nav aria-label="Main">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/products">Products</a></li>
<li><a href="/pricing">Pricing</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>


Если при нажатии на пункт открывается вложенное меню, диалоговое окно, меняется часть интерфейса приложения, происходит какое-то действие с данными, меняются настройки, режим работы и т.д. — это меню. Для этого нужно использовать паттерны menu и menubar. Так как встроенных в HTML аналогов нет, то меню можно сконструировать из семантически-нейтральных элементов и соответствующих ролей. Часто его делают из списка. В этом есть смысл, но я предпочитаю использовать кнопки с ролями, так как они сами по себе интерактивные, в отличие от элементов списка.

<div role="menu">
<button type="button" role="menuitem">Save...</button>
<button type="button" role="menuitem">Save As...</button>
<button type="button" role="menuitemcheckbox" aria-checked="false">Autosave</button>
<button type="button" role="menuitem">Open</button>
<button type="button" role="menuitem">Undo</button>
<button type="button" role="menuitem">Rendo</button>
</div>


Контекстные меню, открываемые щелчком правой кнопкой мыши по элементу или при помощи сочетания Shift+F10 на Windows — это тоже меню. Но не используйте роли menu и menubar для навигации на сайте.
  • 🔥 13
  • 👏 2
  • ❤ 1
  • 👍 1
More from @alexnozer_dev
  1. Sep 21, 2026Реализация пользовательских атрибутов Под конец прошлого года я рассказывал об API пользов…
  2. Sep 14, 2026Подклассы Event вместо CustomEvent Многие библиотеки предоставляют систему событий в качес…
  3. Sep 11, 2026Эволюция стилей в темах Shopify Адам Ватан на днях поделился новостью, что Shopify выкупил…
  4. Sep 9, 2026Persistent Widgets Многие сайты не должны быть SPA. Но иногда эта архитектура продиктована…
  5. Sep 7, 2026Processing Instructions и маркеры В DOM всё представлено в виде узлов (Node) разных типов.…
  6. Sep 1, 2026@scope и потоковая передача HTML Ноам Розенталь поделился интересной техникой, в которой с…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →