About This HTML Issue
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>
Find issues like this automatically
Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.