How can i make a CSS drop down menu accessible for keyboard navigation?
Thanks to Shannon Youg who tried to help.
I found a solution, but I had to put some Javascript to make it work.
HTML:
<div class="my-menu">
<a id="menuUser" href="javascript:showHideMenu()" class="">
<div>
Test
</div>
</a>
<ul id="menuUserDropdown" class="menu-dropdown">
<li>
<a href="#" class="menu-dropdown-item">
Option 1
</a>
</li>
<li>
<a href="#" class="menu-dropdown-item">
Option 2
</a>
</li>
<li>
<a href="#" class="menu-dropdown-item">
Option 3
</a>
</li>
</ul>
</div>
CSS:
.my-menu a{
display: inline-block;
font-family: 'OpenSans Bold';
font-size: 16px;
color: #646464;
text-decoration: none;
cursor: pointer;
position: relative;
}
.my-menu a div{
padding: 4px 5px 4px 0;
}
.my-menu a.opened div,
.my-menu a:hover div{
background-color: #c9252b;
color: #fff;
}
.my-menu .menu-dropdown.opened{
display: block;
}
.my-menu div{
display: inline-block;
vertical-align: middle;
}
.my-menu .menu-dropdown{
display: none;
margin: 0;
position: absolute;
z-index: 30;
background-color: #FFF;
list-style: none;
padding: 0;
border: 1px solid #b4b4b4;
}
.my-menu .menu-dropdown-item{
display: block;
background-color: white;
padding: 12px;
text-decoration: none;
width: 162px;
cursor: pointer;
font-size: 16px;
color: #323232;
}
.my-menu .menu-dropdown-item:focus,
.my-menu .menu-dropdown-item:hover{
background-color: #b4b4b4;
color: #fff;
}
Javascript, well, I made with GWT, but the logic is simple:
/* Just add or remove the class "opened" from "menuUser" and "menuUserDropdown".
You can put a "blur()" and "mouseLeave()" functions
to close the menu when the user moves away the cursor or
move the focus out of the menu too. */
Javascript and css accessible dropdown menu
The solution is add this extra on:
// If sub menu is already open
if ( $(this).children('a').hasClass('js-openSubMenu') || $(this).children('ul').hasClass('js-showElement')) { ... }
else { ... }
Thank you everything.
Making my drop-down menus accessible when only using the keyboard
Looking at the tutorial, it is not really a good starting point to make fully keyboard accessible. Unfortunately it isn't just a matter of showing the drop-downs when pressing tab.
Once you get past a couple of items in each drop-down it it not a good thing for keyboard users to have to tab through every option.
There are two main ways to make this type of menu accessible:
Traditional method: Make each top level link go through to a landing page that includes the links from the menu, and hide the drop-downs from keyboard use.
HTML5 (new) method: Use WAI-ARIA markup and lots of scripting to enable full keyboard accessibility.
The traditional method if fairly easy to do, you just need to properly hide the menus that are off-screen using display: none;
on the classes starting .dropdown_1column
. The means keyboard users won't tab through the sub-menus.
And then use display: block
to show the sub-menus on hover (not focus), where the CSS starts:
#menu li:hover .dropdown_1column
To achieve the HTML5/new method I would start with Adobe's open-sourced "Accessible Mega Menu". It would be a huge amount of work to do this from scratch, and unless you know how to test with a wide range of user-agents, it is unlikely to work as well as Adobe's.
Keyboard accessible drop down menu not iterating through sub menu
I use some script to add a class to the item that has focus and walk up the DOM to add it to ancestors so that I can display them. I also remove the class when the focus changes.
It has been a while since I have reviewed it to remove / tweak any dumb bits.
Part of the issue you are having is that you are using display: none
, which means a keyboard will never find it. If you use an off-screen technique, then the user can tab into the control.
Also, please remove role="menuitem"
throughout as well as tabindex="0"
. The former implies interaction you are not supporting (such as the arrow keys) and the latter creates extra tab stops that do not announce themselves correctly to screen readers.
// Get the nav by id
var pNav = document.getElementById("globalNav");
function unClassy(){
try {
// Remove the focus class
pNav.classList.remove("focus");
// Remove the focus class from all its descendents
pNavDesc = pNav.getElementsByTagName('*');
for( var i = 0; i<pNavDesc.length; i++){
pNavDesc[i].removeAttribute("class");
}
} catch (e) {
console.log(e);
}
}
/* For any clicks, clear the focus class from the nav and all its descendants, essentially closing the menu when a user clicks/taps outside of it. */
document.documentElement.onclick=function() {
try {
unClassy();
} catch (e) {
console.log(e);
}
}
/* Manipulate focus classes in navigation. */
function classy(){
try {
unClassy();
// Add the focus class to items that have focus
// Get the element that currently has focus
var focusedElement = document.activeElement;
// If that element is the primary nav, add the class
if (focusedElement.id == pNav.id){
// Add the focus class
pNav.classList.add("focus");
}
// If nav contains the focused element, add the class
if (pNav.contains(focusedElement)){
focusedElement.classList.add("focus");
el = focusedElement;
while (el.parentNode) {
el.classList.add("focus");
el = el.parentNode;
}
}
} catch (e) {
console.log(e);
}
}
/* Delay the assigning of classes to give the :focus a chance to catch up. There has to be a better way for this. */
document.documentElement.addEventListener("keydown", delayClassy, false);
function delayClassy(){
try {
setTimeout(classy, 200);
} catch (e) {
console.log(e);
}
}
Related Topics
How to Create a Text Watermark Without an Image
How to Create a Curve Tail for Speech Bubble with CSS
How to Rotate Clip Path Without Rotating Image
CSS Animation on Hover Stay at Last Keyframe When Using Transform: Rotate
Less: Extend a Previously Defined Nested Selector
Scale Element in X and Y by the Same Amount of Pixels
Combining :Nth-Of-Type() and :Not
Perfect 100% Width of Parent Container for a Bootstrap Input
Can't Use the Same Animation in Reverse for Class Toggle
How to Evenly Distribute Menu Items with CSS When Width and Quantity Is Not Known
Bootswatch Theme in Shiny Flexdashboard R
Two Fixed Width Full Height Columns, with Seamless Transition to Blank Space
How to Make CSS Sourcemapping Work in Chrome with Compass (Sass)
Specifying Different Font-Sizes for Different Font-Families
Img with {Display: Table-Cell} -- Is It a Bug
Laravel 5.3 - Issue Displaying Images from Public Folder Using @Extends & @Sections