HTML Guides for submenu
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
An element with an interactive ARIA role, such as menuitem or button, is nested inside another element whose role already describes a single control, like a menu item inside a menu item.
ARIA in HTML treats an element with one of these outer roles like a native <button>: it can hold phrasing content, but no interactive descendants. Most of them also have presentational children in WAI-ARIA, so browsers don't expose their descendants to assistive technologies as separate elements. A screen reader announces the outer menu item and reads anything nested inside it as plain text. The arrow-key navigation of a menu can't reach a nested item either.
The validator checks descendants at any depth inside elements with role set to button, checkbox, img, link, math, menuitem, menuitemcheckbox, menuitemradio, option, progressbar, radio, separator, slider, switch or tab. It flags descendants whose role is button, checkbox, combobox, grid, gridcell, listbox, menu, menubar, menuitem, menuitemcheckbox, menuitemradio, option, radio, scrollbar, searchbox, slider, spinbutton, switch, tab, textbox or treeitem.
Nested submenus are the most common cause. A site menu gives each <li> role="menuitem" and puts the submenu, a <ul role="menu"> with its own menu items, inside that <li>. Each submenu then gets one warning for the role="menu" list and one for every item in it. If the <li> elements also hold links, those links get their own warnings, starting with "The element "a" should not appear as a descendant of an element with the attribute "role=menuitem"." The same fix clears all of them.
In the WAI-ARIA menu pattern, a submenu sits next to the item that opens it, not inside it. Give each <li> role="none", put role="menuitem" on the link or button inside it, and place the submenu <ul role="menu"> after that element in the same <li>. Add aria-haspopup="true" and aria-expanded to the parent item so screen readers know it opens a submenu.
If the list is ordinary site navigation, remove role="menubar", role="menu" and role="menuitem" altogether. The menu roles are meant for application menus like the ones in desktop software, and they need scripts that move focus with the arrow keys. A <nav> with nested lists of links and a <button aria-expanded> for each submenu needs no ARIA roles.
Other role combinations have the same fix: keep one interactive role per control. Move the role onto the element that performs the action, or move the inner control out of the outer one.
Invalid example
<ul role="menubar" aria-label="Main">
<li role="menuitem" aria-haspopup="true" aria-expanded="false">
Services
<ul role="menu" aria-label="Services">
<li role="menuitem">Consulting</li>
<li role="menuitem">Training</li>
</ul>
</li>
</ul>
Valid example
<ul role="menubar" aria-label="Main">
<li role="none">
<button type="button" role="menuitem" aria-haspopup="true" aria-expanded="false">Services</button>
<ul role="menu" aria-label="Services">
<li role="menuitem">Consulting</li>
<li role="menuitem">Training</li>
</ul>
</li>
</ul>
Valid example for site navigation
<nav aria-label="Main">
<ul>
<li>
<button type="button" aria-expanded="false" aria-controls="services-menu">Services</button>
<ul id="services-menu" hidden>
<li><a href="/consulting">Consulting</a></li>
<li><a href="/training">Training</a></li>
</ul>
</li>
</ul>
</nav>
Validate at scale.
Ship accessible websites, faster.
Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.
1K Weekly
1,000 monthly checks. Cancel anytime.
Get 1K Weekly →Join teams across 40+ countries