Тег menuitem в HTML: зачем нужен был и как сделать меню сейчас

Тег <menuitem> (от английского menu item, «пункт меню») задумывали как один пункт контекстного меню: пользователь нажимает правой кнопкой мыши, и браузер показывает меню, которое собрал автор страницы. Пункты записывали внутри <menu type="context">. Закрывающий тег </menuitem> нужен: без него следующий пункт вложится в предыдущий.

Идею из стандарта HTML убрали. По умолчанию такое меню показывал только Firefox, да и тот отключил. Сегодня menuitem для них неизвестный тег: нарисовать меню он не может. Новые страницы с ним писать не нужно, меню собирают из menu, button и атрибута popover.

HTML
<menu type="context" id="ctx">
  <menuitem label="Копировать"></menuitem>
  <menuitem label="Вырезать"></menuitem>
</menu>
<div contextmenu="ctx">Правый щелчок здесь</div>

Тег menuitem в HTML: что это и для чего создавали

Раньше контекстное меню страницы, то есть меню по правому щелчку, нельзя было собрать на чистом HTML: приходилось писать скрипты. Для этого придумали пару из menu и menuitem. Меню связывали с любым тегом атрибутом contextmenu, а пункты описывали в menuitem.

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

АтрибутЧто делал
labelназвание пункта меню, показывалось в меню
typeвид пункта: command, checkbox или radio; нужен для флажков и переключателей
iconадрес картинки рядом с названием
disabledпункт нельзя выбрать
checkedотмеченное состояние флажка или переключателя
radiogroupназвание группы переключателей для type="radio"
defaultпункт по умолчанию

Родителем пункта служил menu type="context". Сам menu остался в HTML как список команд, а вот его тип context и теги пунктов из стандарта убрали.

Как записывать menuitem: закрывающий тег нужен

В старой спецификации menuitem считался пустым тегом, но браузеры так его не разбирали. Сегодня это неизвестный тег, а у такого закрывающий нужен. Если закрывающий </menuitem> не записать, каждый следующий пункт попадёт внутрь предыдущего: у menu останется один дочерний тег, а остальные вложатся друг в друга.

HTML
<menu>
  <menuitem label="A">
  <menuitem label="B">
  <menuitem label="C">
</menu>

Пример: как браузер разбирает menuitem

Результат

Кнопки меняют запись. Под ней показаны число дочерних тегов у menu и глубина последнего пункта.

Работает ли menuitem сейчас

Нет. Браузер создаёт для menuitem неизвестный элемент: класса HTMLMenuItemElement в нём нет, а у тега нет ни свойства label, ни других свойств пункта. По умолчанию display у него inline. Название из label не рисуется, а текст внутри показывается как обычный строчный.

Атрибут contextmenu тоже не работает: у тегов нет свойства contextMenu, а правый щелчок открывает обычное меню браузера. Тег menu с type="context" остаётся простым блоком и ничего не показывает.

JavaScript
console.log(typeof HTMLMenuItemElement);
console.log("contextMenu" in HTMLElement.prototype);

Пример: что делает браузер с menuitem

Результат

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

Какие браузеры понимают menuitem

Данные взяты из таблицы совместимости caniuse: там тег отмечен как удалённый из стандарта HTML.

Пример: таблица версий

БраузерКогда понималЗаметка
Chromeнетверсии 41-60 понимали тег только за флагом, отключённым по умолчанию; с версии 61 нет совсем
Edgeнетни в одной версии
Firefox8-84понимал частично; с версии 85 отключён по умолчанию
Safariнетни в одной версии

Чем заменить menuitem: menu с button и popover

Меню собирают из обычных тегов. Простейший вариант: menu со списком li, а в каждом пункте button. Кнопки получают фокус с клавиатуры, поэтому отдельный скрипт для доступности не нужен.

HTML
<menu>
  <li><button type="button">Копировать</button></li>
  <li><button type="button">Вырезать</button></li>
</menu>

Чтобы меню открывалось как всплывающее, добавляют атрибут popover и кнопку с popovertarget. Браузер сам показывает и скрывает такой блок поверх страницы, а в CSS его состояние описывает псевдокласс :popover-open.

HTML
<button type="button" popovertarget="pp">Меню</button>
<div id="pp" popover>
  <menu>
    <li><button type="button">Копировать</button></li>
    <li><button type="button">Вырезать</button></li>
  </menu>
</div>

Контекстное меню по правому щелчку собирают скриптом: слушают событие contextmenu, отменяют меню браузера и открывают свой блок с popover методом showPopover().

JavaScript
area.addEventListener("contextmenu", (e) => {
  e.preventDefault();
  menu.showPopover();
});

Пример: меню без menuitem

Результат

Кнопки переключают вариант: список кнопок и всплывающее меню. Состояние popover читается из страницы после каждого нажатия.

Частые ошибки с тегом menuitem

Почти все ошибки с menuitem от ожидания, что браузер покажет меню.

ОшибкаЧто получитсяКак исправить
menuitem без закрывающего тегаСледующие пункты вкладываются друг в друга, у menu один дочерний тегЗакрывать каждый menuitem
menu type="context" с атрибутом contextmenuМеню не появится, правый щелчок открывает обычное меню браузераСобытие contextmenu и блок с popover
Название пункта только в labelНичего не рисуется, размер 0 на 0button внутри li
menuitem type="checkbox" или type="radio"Флажка и переключателя нетinput type="checkbox" или type="radio"
menuitem в новых страницахВалидатор HTML показывает ошибку: тег устарелmenu с button или popover
Категория
Поделиться в социальных сетях

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×