Talk by Adam Berkowitz
No matter how users get to your sites, they deserve an inclusive, accessible experience. A main navigation component built with accessibility in mind goes a long way towards this goal. Fortunately, WordPress leaves the implementation of accessibility best practices up to theme and plugin developers. This means that by carefully thinking about how to build a menu from ”the ground up”, we can help all of our users use our sites better.
This presentation will demonstrate:
- The basics of menu accessibility
- How a custom WordPress Walker class can be used to create accessible markup
Watch Adam’s Presentation
Mike: Hello and welcome back to the WP Accessibility Day, one o’clock a.m. UTC session. If you have any questions, our chat moderator Kayla will be answering them.
So please put the questions that you have for our speaker. Please remember that we are welcoming community and there is a code of conduct in force during this entire event and you can find slides and Twitter links all the information on our website at wpaccessibilityday.org.
Our speaker right now is Adam. Adam is a Web Developer at the University of Connecticut, or Uconn in the role at the Office of University Communications. He specializes in WordPress Application Development and Web Accessibility. He’s also been on the Accessibility and Diversity Committees at Uconn.
These include Uconn’s Innovation and Communication Technology Task Force and University Communications Diversity Equity and Inclusion Task Force. When he’s not working he enjoys reading, martial arts and spending time with his family. So it’s my pleasure to welcome Adam and his talk, Accessible Navigation from Scratch.
Adam: Hi everybody uh let me see if I can get my screen shared, make sure this works correctly and I think that should do it. Okay, excellent. So uh thank you very much for that terrific introduction um and thank you all for being here with me uh.
I hope that you’ve enjoyed everything so far and learned a lot from the other presenters today. So the web team in our office focuses on top level and strategic marketing sites, such as uconn.edu which is our main university website, our regional campus websites and hospital network. And as you can imagine, these get a lot of traffic and we need to make sure that they are as accessible and and welcoming as possible to everyone who visits.
A few years ago, um the World Accessibility Day New England Conference was held at the university. Pretty much everyone from our office’s web team attended. As the conference went on, it became very obvious, very quickly, how much work we needed to do. One of the things we looked at on our sites, was the main navigation components. As a state institution, we had some pretty specific requirements.
And we also wanted to do the right thing and have our websites be as good as they could be. So one of the things after that conference was, I wanted to improve these navigational elements which leads us here today. Now I’d like to point out that this project and presentation are based on the majority of the needs for sites currently in use at the University of Connecticut.
So even if you choose not to use the specific approach I’ll show you, the basic ideas can be adapted to a wide range of sites. Now unless you’re building a site which is only one page, people are going to have to find their way around and not only that, but as a web developer I know that if I put something or really anything interactive on a site, people are going to try and use it.
So that means interactive elements may get used in ways that are unexpected or unfamiliar to me. As developers, just like we validate forum inputs, because we can’t anticipate every single thing someone might enter, we need to consider how people will use our sites besides with a mouse and screen. In terms of accessibility, this concept applies to visitors with permanent disabilities first and foremost.
At the same time, some visitors may have a temporary or contextual accessibility need with respect to a site. Their mouse might break, they might be working on an airplane going through turbulence, their dominant hand might be broken or maybe they visited an eye doctor and got their pupils dilated, we just can’t know.
We can’t know the situation for every single person who visits us, but we can try to design, build and prepare sites in the most equitable ways we can. So how can we make sure this happens? Well we try to keep our sites POUR.
You may have heard or seen this acronym POUR in the past, but what does it mean in the context of a navigation menu? In my view, Perceivable means if a visitor can physically see the menu, it must be visible or be able to be made visible.
If that visitor can’t physically see the menu, a screen reader should detect and announce items. For the menu to be Operable, someone should be able to interact with it, with the mouse and or the keyboard. If someone uses a mouse and there are sub-menus, they need to be resilient. That is, the sub-menus can’t disappear immediately.
Further, all the items in a sub-menu need to be reachable with a mouse or a keyboard. For the menu to be Understandable, it should behave in a predictable way. Therefore, it needs to maintain visual and auditory consistency. For instance, if an icon toggles between two states, such as open and closed, it should do that predictably.
Overall, I think these cases are pretty common. First a link by itself which we can easily rely on WordPress to handle. After that we identified two types of sub-menus.
Those that have a link to a top level page with sub-pages beneath and menu items that need to be, and menu items that need to solely act as a toggle to a series of sub-items. These are fairly typical types of elements in a nav menu.
Either you want to go somewhere by following a link, or you want to reveal more choices through some kind of toggling action. So now that we’ve got our goals through the POUR acronym and our cases, we need to have a good idea of what elements are available to build with.
Fortunately, WordPress has a built-in way to generate a menu with the wp_nav_menu function. And I’m sure that many of you are familiar with this.The good news is that wp_ nav_menu is easy to use and get started with. It accepts a list of arguments that provide a fair amount of customization quickly and then after that, as soon as the page loads, it displays a menu.
One argument which I tend to change immediately, is the container argument. By default, the menu will be contained by a div. This isn’t ideal for a navigation menu of this type, because a div doesn’t impart any structure or meeting on its own, but you can set the container to a nav element.
When you do this the final output of the menu will be wrapped in a nav tag. Browsers will then detect the tag and create an implicit ARIA role for it, with a landmark.This is a useful accessibility improvement, because a screen reader will have an easier time parsing the document’s content. There are other arguments which you may be familiar with as well.
For instance, you can set custom classes or IDs or set a theme location. Depending on how many navigation sections you have on the page, you might also set the container, or ARIA label argument as well, to further clarify the menu’s purpose. Now wp_nav_menu works really well for menus that have only one level of content. However, once you add depth to the menu, you’ll run into accessibility issues.
Let’s take a look at how wp_nav_menu interprets each of the three cases I shared, then we can see how we might improve their accessibility. The markup for a plain link is pretty straightforward. WordPress gives us just what we need, an anchor tag with a URL. This will provide a nice accessible link that supports people who use keyboard navigation and or screen readers. So far so good. After this, things start to get complicated.
In this case, we want to provide the ability to either click on a top-level link to visit a page or access items in a sub-menu. As the markup is now though, we run into a couple of things that could be better.
First the aria-label attribute on the link takes precedence for screen readers over the content inside of the anchor tag. So instead of a screen reader saying the inner text of the link which is About Us, it will say the value of the aria-label which is just sub-menu. That’s not terribly descriptive, because someone might want to click the link.
Next, aria-haspopup will announce to a screen reader that a pop-up is available, but we’re missing supporting ARIA attributes to associate the link with a specific sub-menu and indicate if that sub-menu is open or closed.
Last, depending on how the sub-menu is hidden and shown, there might be no good way for people who use a keyboard to get to it effectively. In addition, aside from showing the sub-menu when the mouse hovers over the list element, it’s not clear how we can open the sub-menu.
That included things like being able to distinguish between links that go somewhere and toggles that don’t. More ARIA attributes to support people who use screen readers, custom classes, icons and so and so on. WordPress does provide some additional filters for navigation menus such as wp_nav_menu items, wp_nav_menu_object filters.
However, I wanted to be able to create the same kinds of markup across a variety of themes. For us, this would help with our brand consistency and visitor expectation from one site to the next. Fortunately, we can tap into an override the core class wp_nav_menu uses to generate the output for a navigation menu.
We can do this with a custom Walker class. To make it portable we can then turn that into a Composer package that can be installed from GitHub or Packagist. The project can then be used in many places.
The Walker_Nav_Menu class is part of a collection of Walkers which all inherit their functionality from a general Walker class. Now to be completely honest, when I started looking into this back then, the Walkers were incredibly confusing. Fortunately, these classes take care of a lot of the work for us though.
For example, we don’t have to worry about writing our own recursive functions to traverse menu structure since that’s their main purpose . Rather we can focus on logic for the markup our menu might need and what the output should look like.
Once you write your a custom Walker class you can then add it to the list of arguments used by wp_nav_menu.
When you do this, all the markup created by wp-nav-menu will flow through the Custom Walker. This means that you can override any of the Walker nav menu’s methods, with your own and that’s what wp_nav_menu will use. There are four class methods available which will let you start a level, start an element, end an element and end a level. In this context, we only need two of those. The one to start a level and start an element.
Every item in the menu is going to pass through the start_el and end_el methods.These methods are where we can add logic to support the type of markup we want to build.
Consequently, the start-el method was where most of the work for my Custom Walker happened. However, we’re not just dealing with a flat menu, we need to be able to add depth as well. When we create a nested sub-menu the Walker will pass the output for the markup through the start and end level methods as well. These create the unordered lists. We can take advantage of that to affect how the submenu unordered list elements get created.
In terms of accessibility, we can make sure we’re adding useful IDs to each level for example. By default WordPress wasn’t doing this, or at least I don’t remember it doing it back when I started this. It may do it now. This will let us match up the sub-menu to an aria-owns property in the items markup.
Now that we’ve seen the path the markup takes through the Walker class, let’s zoom in to the start_el method where most of the logic happens. Here I’ve written out some pseudo code to describe the flow through our custom start_el method.
The shell of this is exactly what you would see if you took a look at the Walker. We can start by checking to see if the current item has children. That is, should it be a link by itself, or should it have a sub-menu with it.
If not, if it’s just a link by itself, we can output the start of a list item with a link inside and then finish. Otherwise, we need to know if the top level item should be a link or a button. If it doesn’t have a link, we can output the start of a list item with a button on the inside.
Otherwise, we need both a link and then a button as a sibling. This way we can account for all the cases in the markup. With this logic in place we can also do things like add additional custom classes and data attributes. Those can help us style and interact with the menu more easily.
Let’s look at some examples of the output that the Custom Walker I wrote, creates. So here we’re back at our plain link, but notice that we’ve added prefixed am dash classes in addition to the standard WordPress classes. These will help designers and developers create styles specifically for these types of menus without relying on WordPress classes. There’s also a no.js class on the element.
Here’s how we can improve the markup for linked items with sub-menus. First, instead of the link, links aria-label only saying sub-menu, it now describes the text of the link and gives a hint about how you can interact with it. You can obviously change this to whatever is appropriate for you.
Here we can use the aria-hidden property. The aria-hidden property will hide only the icon from screen readers, but still leave it visually available. Since we’ve created screen reader accessible text on the button with the aria-label property and added the aria-expanded property, we can use aria-hidden to hide the icon without a problem. The aria-owns property will associate the button with the sub-menu that with the sub-menu with the aria-owns property or the correct ID rather. This works in a way similar to how a label is associated with a form element.
This is now markup that will let a visitor choose between clicking on a link or opening up a sub-menu.
In the last case, there is no link for the item. It’s replaced entirely by a button, so it can always act as a toggle. You can imagine that if you combine all these cases you can start to get a very flexible and accessible menu, but we’re not quite done yet. So far we’ve made sure that people will be able to interact with the menu with a mouse, keyboard, keyboard and a screen reader, but now we have to think a little bit more about design and interaction.
In our context, we wanted menus to work primarily through toggling action.
Actually, um as I was writing this, I forgot one thing and I added this slide today. So as I was preparing the presentation I realized I had made a mistake. Uh, in the navigation menu you want to have the current, the current page and or its top level parent visually highlighted somehow, and this lets people know which page is active.
WordPress gives classes for this, but also you want to make sure that the aria-current property is set on pages. Prior to WordPress 5.3 I think, you had to do this manually. Typically, you could check the, you could do this with the nav_menu_link attributes filter, but in checking, this filter doesn’t seem to work with the custom Walker I created. I’m not entirely sure why right now, so I’m going to have to go back and refine it, but that’s okay.
I think the more important thing is to note that even while trying my best, I still ended up missing something by accident, which is all the more reason for me to keep learning and researching.
Now I’m not going to go over everything in the CSS for this project, but rather focus on CSS related to hiding and showing content. When we use CSS to hide and show content, our choices affect how people who use screen readers and keyboards can or cannot interact with web content.
The ability to show and hide content is an important part of user interface and user experience design. This is especially true for navigation menus where we often want to hide or show content on hover or focus. If we’re not careful, we can inadvertently use CSS to create an inaccessible experience for our visitors. So I think that it’s important to understand the accessibility implications of how we use CSS to accomplish this.
There’s several cases where this chart is important. We might consider the case where a visitor who uses a screen reader wants to skim all the links on a site. We should be aware that if we use display:none or visibility:hidden, we’ll be hiding content from them. Another visitor may come to our site and have an issue with motor control and browse with a keyboard. Depending on how we hide and show content, our choices may make that user experience more or less accessible.
If the links in the navigation menu can be found in other ways or duplicated somewhere, that may not be a problem. But we should think about our choices and the overall context of the site as we make them.
One way to do this is the focus-within pseudo class which I’ll describe in a moment. You should be aware though, that focus-within isn’t supported by Internet Explorer or non-chromium versions of Microsoft Edge.
In other words, it represents an element that is itself matched by the focus pseudo class or has a descendant that is matched by focus.” In plain terms, this means that even if a parent element can’t be focused, if a child element can, the entire structure can be styled as if the parent can be focused, That’s why it can be applied to the unordered list element, instead of an anchor tag.
Typically unordered list elements can’t receive focus, but because the list can contain an element like a link that can receive focus, the list will respond to the focus-within class. Here’s a small demonstration. The markup for each of these menus is exactly the same. You can confirm as much by going to the CodePen linked in the slide. The only difference is the use of the focus-within selector.
You can see that on the left, the sub menu elements for the About Us menu item aren’t reachable by keyboard. However, on the right you can tab through them as you would the top level links.
Here is an example in context. The Admissions and About elements are links with buttons to toggle sub-menus next to them as siblings, symbolized by the carrots.
In this project when a button is clicked the aria-expanded state changes from true to false or vice versa. The CSS is then set up so that the button’s icon will be changed depending on the state. This provides both visual and auditory context for sites visitors as they use the menu.
This approach may be less flexible than something with a larger API. However, I believe in this context it’s a good trade-off, because developers with a wide range of experience will be able to use it more quickly. In fact, as a university, sometimes we have student developers who work on our projects.
The dispatcher determines the type of event and routes it to a particular eventHandler. Once the event is properly dispatched to the handler, it’s responsible for the logic to set the state of menu items and properties. Depending on the state of the menu, eventListeners are also added to the document, so people can close open sub-menus, with the escape key or by clicking outside the menu area.
That way I could handle exceptions for each type of event while encapsulating other parts of the code for reuse. One thing to note here, is that these menu follow the disclosure design pattern for navigation menus. As I understand it, in terms of keyboard support, this means that they’re required to do three things. Move among items with the Tab key, be able to select and activate items once they’re focused with the Space or Enter key and close items with the Escape key.
This is very different than an element with the Menu ARIA role. The Menu ARIA Role requires more types of keyboard interaction, such as the ability to use arrow keys. However, in the example linked in the slide, well it doesn’t appear to be linked in the slide, sorry about that.
We’ll get that later.
Uh the markup is trying to create something more like an application menu for a text editor. If it turns out that I’m completely wrong about this, and that I need to add more keyboard support to the menus, that’s okay.
Earlier this morning I read an article about WCAG 2.2 and for all I know I’ll need to bring this project up to date to conform at some point to that, or a future version.
You can also see the relevant icon stays changed as well, until someone leaves and closes the menu. This is done by tying the CSS to the aria-expanded attribute of the toggle.
Here are just a few resources collected into one place. I listed a few of the themes this project is part of, just to demonstrate how it can be styled in different contexts. This variety is why I wanted to make sure that the project was portable and which is why we chose to bundle it as a Composer package.
I thought it would also be helpful to give a few code resources and documentation as well. You can browse the repo we use and if you like contribute to help improve it.
So to wrap things up, there’s still quite a lot to do, even after so much time. Web Accessibility standards continue to be updated and refined. Plus, as I’ve shown, there’s at least one thing that I’ve missed and need to revise. So personally, I want to make sure that I stay informed and engaged with issues around accessibility, so I can be of service to the people who visit us.
So to finish up, I’d like to thank all of you for being here with me. And I’d also like to thank everyone involved with today’s conference for giving me some time to share this with you all.
If you have questions, I am more than happy to answer them. Let’s see if I can stop the screen sharing.
I can turn my camera on, right? Is that okay? Yeah okay.
Mike: Yes, definitely. Hey.
Adam: There we go, I did that. Hey it’s good to see you in person.
Mike: Nice to see you in person uh in the, in the Inter webs as it were. So yeah um,great talk uh very informative. What is the project license? What’s the open source license, is it MIT, GPL?
Adam: You know, I don’t remember off the top of my head. It is probably a very broad, broad license. I mean this, this was basically um this was basically we looked at the websites that we had and realized that these, beyond just ordering things with proper uh you know H1 H2 H3 right, there were some broader issues involved that at a technical level we were going to have to deal with.
And this was the first one I wanted to tackle, because it seemed like it was going to be one of the most difficult um. So I think the license is, if I even wrote one is very broad. Yeah.
Mike: Fair enough. I always just find that interesting, uh how people license things um, but anyway I’m a geek so uh. We have some questions and if you still have questions um please put them into the chat and Kayla our chat moderator will send them over to me and then I’ll say them out loud and then Adam will answer them. So our first one is, is a mega menu accessible accessibility suited or can it be made usable? If so can you describe or provide a sample?
So I think is a mega menu accessible or can it be made accessible?
Adam: I mean, I guess that would entirely depend upon whether or not it conforms to WCAG standards, right. So can you navigate the menu using a mouse and or a keyboard, uh does it respond appropriately to a screen reader, when you do so? Um so for instance my, just so you all know, my reference point for screen readers is the Mac OS screen reader.
I honestly, I don’t have JAWS or anything like that and we don’t really have to have have that kind of material where I work. But I try to use the Mac OS screen reader as best I can. I would say that yeah, you should just be very careful in the case of a mega menu, because you may inadvertently hide content that you would rather have people get to.
Um yeah, so I think that what you should do in the case of a mega menu, is try to navigate the site with the screen reader and see what happens if you, like can you actually get to any of the items? Um can you get to the items if you only navigate by keyboard? Yeah and I think that will be the determinant if it’s accessible or not, better than me just giving a broad, you know, yes they are, no they’re not, yeah.
Mike: Sure, our next question is um, how have you found the experience to be for voice command users when using ARIA label to provide the accessible name?
Adam: Uh so is the question, I guess I’m not quite sure I understand the question. Is the question, does it read the name appropriately?
Mike: I think so um I mean I.
Adam: I, yeah I believe that it reads, last I checked it did um.
I mean, it’s certainly, we don’t have anything that responds to voice commands uh in these menus. Um certainly I, I don’t have the background to handle that. Although if it’s something that I need to do, I can certainly start looking into it. But as best I know, uh and the last time I checked, yes they, they all read correctly.
Mike: Okay. And our last question, and if anyone has a last minute question, please put it into the chat now and we’ll try to get to that um uh is, menus seemed um a web feature that hasn’t gone away over time.
With Skip NAV and one-page sites becoming more prevalent, do you see them being phased out for simple more accessible experiences?
Adam: Oh that’s actually really interesting um.
So we definitely use Skip NAV. Um I’m not, I have no information about how many people actually use that. Um as far as single page sites go, uh you know I think there’s a big difference between literally a single page which is like a brochure and a single page application site, which is a more larger scale or something like that. Um in the latter case or in the in the former case rather, a single literally single page, yeah I’m not quite sure why you would necessarily need a navigation.
Um you might just have like some links at the top that would jump you up and down. In the latter case, I’m not sure. I think that some applications in site are so complex that you wouldn’t necessarily need them. I think the only thing that I would say is, lots of people now get to sites just by Googling the information they want.
Um and then my intuition is that if for some reason the content doesn’t make sense, or is structured in a bizarre way, then they might need to use, uh more navigational elements in order to find what they’re looking for, after the fact.
Mike: Sure, okay. Uh well um again I just want to thank you so much Adam for sharing your expertise. Are you, you listed your contact information on the slide and if you want to get those slides you can go to wpaccessabilityday.org to download all of the slides and find out information about all of our speakers and our wonderful sponsors. Please continue the conversation on Twitter. Our hashtag is wpaccessibilityday and #wpad2020.
And our Twitter account is wpaccessibility.
Plea, at the 2 o’clock UTC hour please join me um and Christina Workman and she’s going to talk about Accessible Websites Benefit Everyone. Um and again, just a big thank you to our chat moderator Kayla um. She is uh stepping away and we’re getting a new chat moderator at the next hour. But again thanks Adam and thanks everyone for watching and being part of WP Accessibility Day 2020.
Adam: Thanks, thanks Mike. Thank you very much.
WP Accessibility Day has not assessed speaker-provided presentation resources for accessibility.
Questions on “Accessible Navigation from Scratch”
Is a ‘mega menu’ accessibility suicide or can it be made useable? If so, can you describe or provide a sample?
Well I’d hate to think that making a mega-menu is suicidal! I think that with most interfaces, we can look for accessible solutions. In this case, I would suggest a developer ask some critical questions:
– Can a visitor operate the menu with a keyboard?
– Can a visitor who uses a screen-reader get valid, useful, and equitable information from the menu?
– Does the markup support appropriate ARIA attributes?
– Does the menu conform to WCAG expectations?
You could probably think of many more questions as well.
But, I think there’s another larger question here especially if we’re building from scratch and not remediating a site. Who is the audience for this interface and why do we think they want it? That is – are we adding something because WE think it’s interesting? Are we adding it because some “higher ups” want it? Or is this piece of interface something that will actually help visitors? Sometimes, the answers to those questions may conflict. Other times they will overlap.
In any event, I think that it’s often useful to examine areas where we can step outside ourselves and be imaginative. Ask yourself – “What would it look like if….?” and go from there.
I hope this helps!
How have you found the experience to be for voice command users when using aria-label to provide the accessible name?
Sadly I don’t have very good information to give you on this question. It is likely something I should investigate more thoroughly.
Menus seem a web feature that hasn’t gone away over time. With SKIP NAV and one page sites becoming more prevalent, do you see them being phased out for simple, more accessible experienes?
In short – no. I don’t foresee menus going away any time soon. That being said, there are two things here. One is that we should distinguish between sites which are literally one page and sites which are essentially single page applications. In the case of a site which is like a brochure site or landing site, a navigation component may not be necessary whatsoever. Or, it may just be a collection of anchor tags. In the other case, people need some way of getting forward and back, managing information, organizing their browsing, knowing what to expect, etc…
The thing about a menu is that it’s not just an interface. It’s a graphical or structural representation of what the site authors believe is important. I don’t think their desire to demonstrate that is going away any time soon.
I hope this helps!
Do you think WordPress should have its own automatically accessible menu?
This is something that I’ve thought a lot about since starting this project. Basically, I think – yes. It’s good to move in the direction of more accessible markup. I think that adding aria-labels to submenu toggles is a useful improvement which could be refined a bit. It also gives developers a clue to look into the markup more closely.
That being said, I believe it is absolutely up to developers to take the many functions, filters, and classes currently available in WordPress to create accessible menus. This flexibility is, I think, a strength rather than a weakness. Is there room to grow? Yes. But perhaps what the core documentation should emphasize is something like – “this is how you use the nav_menu_link_attributes filter to create a more accessible menu”.
I hope this answers the question! Feel free to be in touch if you like.