v143 · html · menus
<menubar>, <menulist>, <menuitem>
The existing <menu> element is a list with a misleading name — it is exposed as a list, behaves as a list, and has never been a menu to anything that reads the page. Three new elements give the platform an actual menu: a bar, a list that opens as a popover, and an item that invokes a command.
concepts
-
What actually landed
A draft specification and a partial implementation rarely line up. Read each element's real interface, its user-agent styling, and which pieces of the proposal this browser has — measured from the elements themselves rather than from the explainer.
-
A working menu bar
File, Edit, View, built out of the elements and opened with invoker commands rather than script. Keyboard-operable, with the fallback shown honestly when the browser does not know the elements.
-
Commands, checkboxes and radios
Menu items carry state as well as actions. Probe the command vocabulary by reflection, and see which of
type,checkedandfieldset checkableare implemented here — the answer is more interesting than yes.
why it shipped
Every application on the web that has a menu has built it out of buttons and divs, plus a few hundred lines of ARIA and key handling. The result is nearly always subtly wrong: the roving tabindex misses a case, typeahead is missing, Escape closes the wrong layer, and a screen reader announces a list of links.
The new elements move that into the platform. A <menulist> opens in the top layer without a popover attribute, a <menuitem> invokes a command through commandfor rather than a click handler, and the roles come from the elements instead of from attributes someone has to remember to write.
the markup
<menubar>
<menuitem command="toggle-menu" commandfor="file-menu">File</menuitem>
<menulist id="file-menu">
<menuitem command="--new-document" commandfor="editor">New</menuitem>
<menuitem command="--open" commandfor="editor">Open…</menuitem>
</menulist>
</menubar>
No role, no tabindex, no key handler, and no popover attribute — the menulist opens into the top layer because of what it is.
enabling it now
Verified on Chrome 150 on this machine: with the flag off, document.createElement("menuitem") produces an HTMLUnknownElement. With it on, the three elements have their own interfaces, <menubar> gets display: inline-flex from the user-agent stylesheet, a <menulist> is display: none until it is invoked, and invoking one makes it match :popover-open.
chrome://flags/#enable-experimental-web-platform-features
# or, from the command line
google-chrome --enable-experimental-web-platform-features