Make WordPress Core

#58098 closed enhancement (invalid)

Empty top-level menu item to have role=button

Reported by: robanna's profile robanna Owned by:
Milestone: Priority: normal
Severity: normal Version:
Component: Menus Keywords: reporter-feedback
Focuses: accessibility Cc:

Description (last modified by sabernhardt)

For accessibility, an empty top-level menu item should have role="button" added to the custom link.

When setting up a menu with a top-level menu item with a custom link that is blank or to an anchor, the output looks like:
<a>Top Menu Item</a> or <a href="#">Top Menu Item</a>

It should have role=button added when that is the case:
<a role="button">Top Menu Item</a> or <a href="#" role="button">Top Menu Item</a>

Change History (7)

#1 @sabernhardt
15 months ago

  • Description modified (diff)
  • Focuses accessibility added
  • Version 6.2 deleted

Related: #13273

#2 @kelvinballoo
15 months ago

I was not able to fully simulate this issue.

I created an empty empty first and also an anchor link menu on twenty twenty three theme.

Here's the resulting HTML Code:

<a href="#youneverknow" aria-haspopup="true" aria-expanded="false">travel guide</a>

On one hand, I don't have the 'role=button' but on the other, there is the aria tags which actually define it as a button?

This ticket was mentioned in Slack in #accessibility by joedolson. View the logs.

15 months ago

#4 @joedolson
15 months ago

Hey, @robanna! Thanks for contributing. Can you confirm that your request is specific to classic menus, as displayed using wp_nav_menu()? The navigation block handles things differently, so we want to confirm the context.

Historically, the WordPress navigation menu hasn't injected any behaviors into the menu, so I'm not convinced that we want to dictate a change of semantics on top level headings. We do want to make sure that there are always interactive semantics, so making sure there's never a plain <a> element with no target makes sense.

However, the role="button" is only applicable if that top level navigation item is used as a button trigger to open the menu, which will not always be the case - I think it's out of scope for the function to try and observe whether there are click events attached to the menu item.

#5 @joedolson
15 months ago

  • Keywords reporter-feedback added

#6 @brasofilo
15 months ago

It's my first time working with accessibility and arrived here researching this exact matter.
My menu is generated by wp_nav_menu and I've solved the role issue with the following filter:

add_filter( 'nav_menu_link_attributes', function ( $atts, $item, $args, $depth ) {
        if ( $atts['href'] === '#' || empty($atts['href']) ) {
                $atts['role'] = 'button';
    return $atts;
}, 10, 4 );

This plugin has the /following documentation that justifies the need to have "role=button" in empty links:

Why using links for buttons is confusing

When a screen reader user hears “link” or “button” when they encounter an element, this creates an expectation both of how they can interact with the element and what it will do.

For example, hearing “Link. Download” creates an expectation that triggering the element will redirect the user to a different area of the website where they can download something.

In contrast, if you heard “Button. Download,” then you would expect a file to download immediately without having to go to a different page. You would also expect the spacebar to work to trigger the download.

If you use a link instead of a button on elements of the website that are normally expected to be buttons, it can be confusing and disorienting for users because the element will not behave the way they expect it to.

Relevant WCAG 2.1 Success Criteria
1.3.1 Info and Relationships – Level A

This guideline requires that information and the structure of elements can be programmatically determined, which includes the use of proper semantic HTML.

3.2.4 – Consistent Identification – Level AA

This guideline requires that components of a web page that have the same functionality be identified consistently.

4.1.2 – Name, Role, Value – Level A

This guideline requires all user interface components, including buttons, must have a name and role that can be programmatically determined through the code.

Last edited 15 months ago by brasofilo (previous) (diff)

#7 @joedolson
13 months ago

  • Milestone Awaiting Review deleted
  • Resolution set to invalid
  • Status changed from new to closed
Note: See TracTickets for help on using tickets.