HTML Guides for aria-haspopup
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.
The aria-haspopup attribute belongs on the menu item that opens a submenu, not on the role="menubar" element that holds the items.
aria-haspopup tells screen readers that activating an element opens a popup, such as a menu or a dialog. A menu bar doesn't open anything. It stays on screen, and users activate the items inside it. WAI-ARIA 1.2 deprecated aria-haspopup as a global property and lists the roles that support it: application, button, combobox, gridcell, link, menuitem, slider, tab, textbox and treeitem, plus the roles that inherit from them. menubar isn't on that list, so assistive technology can ignore the attribute there, and users can't tell which item has a submenu.
The validator flags any element with an explicit role="menubar" and an aria-haspopup attribute, whatever its value, so aria-haspopup="false" triggers the warning too. If the element is a real menu bar, move aria-haspopup="menu" to each menuitem that opens a submenu, and add aria-expanded there to say whether that submenu is open.
Sometimes the element isn't a menu bar at all. It's a control that shows a dropdown, like a language picker or a mobile navigation toggle. Drop role="menubar" there and use a <button> with aria-expanded and aria-controls, as the disclosure pattern describes. The links inside the panel stay plain links.
Invalid example
<ul role="menubar" aria-label="Editor" aria-haspopup="menu">
<li role="none">
<button type="button" role="menuitem" aria-expanded="false" aria-controls="file-menu">File</button>
<ul role="menu" id="file-menu" aria-label="File" hidden>
<li role="menuitem" tabindex="-1">New</li>
<li role="menuitem" tabindex="-1">Open</li>
</ul>
</li>
<li role="none">
<button type="button" role="menuitem" tabindex="-1">Help</button>
</li>
</ul>
Valid example
The menu item that opens the submenu carries aria-haspopup:
<ul role="menubar" aria-label="Editor">
<li role="none">
<button type="button" role="menuitem" aria-haspopup="menu" aria-expanded="false" aria-controls="file-menu">File</button>
<ul role="menu" id="file-menu" aria-label="File" hidden>
<li role="menuitem" tabindex="-1">New</li>
<li role="menuitem" tabindex="-1">Open</li>
</ul>
</li>
<li role="none">
<button type="button" role="menuitem" tabindex="-1">Help</button>
</li>
</ul>
A dropdown of links, such as a language picker, uses a disclosure button instead of menu roles:
<button type="button" aria-expanded="false" aria-controls="language-list">Language</button>
<ul id="language-list" hidden>
<li><a href="/" hreflang="en">English</a></li>
<li><a href="/es/" hreflang="es" lang="es">Español</a></li>
</ul>
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