What are some ways to ensure keyboard accessibility for a CSS drop-down menu?

I have come across some solutions, but I am struggling to incorporate them into my code as some require elements that are not compatible with my project.

Let's get to the question:

I need help making an existing CSS drop-down menu accessible for keyboard navigation. While I have managed to open the drop-down menu with [Tab], navigating through the options inside has been a challenge.

Here is a snippet of my code:

.menu .options-menu-dropdown{
            display: inline-block;
            font-family: 'OpenSans Bold';
            font-size: 16px;
            color: #646464;        
            text-decoration: none;
            cursor: pointer;
            position: relative;
        }
        .menu .menu-dropdown{
            z-index: -1;
            visibility: hidden;
            opacity: 0;
            position: absolute;
            top: 0;
            right: 0;
            min-width: 180px;
            text-align: right;
            overflow: hidden;
            margin-top: -6px;
            margin-right: -6px;

            -webkit-transition: all 200ms ease-in-out;
            -moz-transition: all 200ms ease-in-out;
            -ms-transition: all 200ms ease-in-out;
            -o-transition: all 200ms ease-in-out;
            transition: all 200ms ease-in-out;    
        }
        .menu .options-menu-dropdown:focus .menu-dropdown,
        .menu .options-menu-dropdown:hover .menu-dropdown{
            z-index: 100;
            visibility: visible;
            opacity: 1;
        }
        .menu .title-dropdown{
            background-color: #005e8b;
            font-size: 16px;
            padding: 8px 6px;
            white-space: nowrap;
            border-bottom: 1px solid #b4b4b4;
            color: #FFF;
        }
        .menu .menu-dropdown-item{
            display: block;
            background-color: white;        
            padding: 12px 32px 12px 12px;
            text-decoration: none;
            cursor: pointer;
            font-size: 16px;
            color: #323232;
            -webkit-transition: all 200ms ease-in-out;
            -moz-transition: all 200ms ease-in-out;
            -ms-transition: all 200ms ease-in-out;
            -o-transition: all 200ms ease-in-out;
            transition: all 200ms ease-in-out; 
            border-top: #b4b4b4 1px solid;
            border-left: #b4b4b4 1px solid;
            border-right: #b4b4b4 1px solid;
        }
        .menu .menu-dropdown-item:last-child{
            border-bottom: #b4b4b4 1px solid;
        }
        .menu .menu-dropdown-item:focus,
        .menu .menu-dropdown-item:hover{
            background-color: #b4b4b4;
            color: #fff;
        }
<div class="menu" align="center" >
          <div class="options-menu-dropdown" tabindex="0">
            <div>Test Menu</div>
            <div class="menu-dropdown">
              <div class="title-dropdown">Opened Test Menu</div>
              <a href="#" class="menu-dropdown-item" tabindex="1">Menu Item 1</a>
              <a href="#" class="menu-dropdown-item" tabindex="1">Menu Item 2</a>
              <a href="#" class="menu-dropdown-item" tabindex="1">Menu Item 3</a>
            </div>
          </div>
        </div>

Code can be found at this link.

Note: I am trying to avoid using any JavaScript solution as this project requires GWT and strictly prohibits the use of JavaScript.

Thank you in advance.

EDIT The menu should behave similarly to Google's account menu, allowing keyboard accessibility to navigate through its options.

https://i.stack.imgur.com/AY9xT.png

Answer №1

I was searching for the same answer and found bits and pieces scattered around the internet. That's why I decided to compile my solution here, which eliminates the need for JavaScript. The key lies in utilizing these pseudo classes:

li > a:hover + ul,
li > a:focus + ul,
li:focus-within > ul

For the complete HTML (Header section):

<header>
    <nav>
        <ul>
            <li>
                <a href="#">Page 1</a>
                <ul>
                    <li>
                        <a href="#">Sub page 1</a>
                    </li>
                    <li>
                        <a href="#">Sub page 2</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">Page 2</a>
                <ul>
                    <li>
                        <a href="#">Sub page 3</a>
                    </li>
                </ul>
            </li>
        </ul>
    </nav>
</header>

Complete CSS (without actual styling) – first level elements are displayed side by side (display: inline-block;), while second level elements remain hidden until parent element is active:

header ul {
    list-style: none;
}

header nav > ul > li {
    display: inline-block;
    vertical-align: top;
}

header nav > ul > li > ul {
    visibility: hidden;
    opacity: 0;
}

header nav > ul > li > a:hover + ul,
header nav > ul > li > a:focus + ul,
header nav > ul > li:focus-within > ul {
    visibility: visible;
    opacity: 1;
}

Answer №2

Check out these Practical ARIA examples by Heydon Pickering:

<nav role="navigation" aria-label="example with dropdowns">
<ul class="with-dropdowns">
    <li><a href="#">Home</a></li>
    <li>
        <a href="/about" aria-haspopup="true">About</a>
        <ul aria-hidden="true" aria-label="submenu">
            <li><a href="/about/#who-we-are">Who we are</a></li>
            <li><a href="/about/#what-we-do">What we do</a></li>
            <li><a href="/about/#why">Why</a></li>
        </ul>
    </li>
    <li><a href="#">Blog</a></li>
    <li><a href="#">Contact</a></li>
</ul>

Answer №3

Big thanks to Shannon Youg for offering assistance.

After some trial and error, I managed to find a solution, although it required incorporating some Javascript for it to function properly.

Here's the HTML code snippet:

<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>

Below is the CSS styling used:

.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;
}
...

And finally, here is the simple logic implemented with Javascript (GWT in this case):

/* Simply toggle the "opened" class between "menuUser" and "menuUserDropdown".
    Optionally, you can include functions like "blur()" and "mouseLeave()"
    to close the menu when the user navigates away from it. */

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Inserting a custom text box underneath the Anything Slider

I am currently incorporating the Anything Slider into a website project. The main purpose of the slider is to showcase videos, but I would like to include a description text box beneath it that dynamically changes based on the selected tab. This snippet de ...

Choose or deselect images from a selection

I am currently working on a feature for an album creation tool where users can select photos from a pool of images and assign them to a specific folder. However, I'm facing difficulty in selecting individual photos and applying customized attributes t ...

The animation in Material UI does not smoothly transition with the webkit scrollbar

I've been experimenting with CSS animations in Material UI's sx property to achieve a webkit scrollbar that eases in and out. However, instead of the desired effect, the scrollbar appears and disappears instantly. Whether I define the keyframes ...

"Implementing a function where two different elements can change the text of a button

I have created a custom FAQ script using dl, dt, and dd elements: $('.faqs dd').hide(); // Hide all DDs inside the .faqs container $('.faqs dt').hover(function(){ $(this).addClass('hover' , 'slow')},function(){ ...

Looping through multi-dimensional JSON objects with jQuery

Hello there, I'm currently facing some challenges in getting the screen below to work properly: Project progress screen I have generated the following JSON data from PHP and MYSQL. My goal is to display the project alongside user images and names whe ...

The 3D card flipping animation is dragging on for an eternity

I'm experiencing a delay in triggering my 3D Card Flip animation on click, and I can't figure out why it's happening. If you want to see an example, please scroll down and click on any black and white picture here: Here is the code I' ...

Conceal the div element when located beneath an ordered list with a designated

I need help hiding the display of comment information if it is a child comment. Below is my attempt to hide the div with the id "info" if the "ol" element has a class of "children". If you have another method for hiding the div when the comment is a chil ...

I have noticed that there are 3 images following the same logical sequence, however only the first 2 images seem to be functioning correctly. Can you help

Update: I have found a solution that works. You can check it out here: https://codepen.io/kristianBan/pen/RwNdRMO I have a scenario with 3 images where clicking on one should give it a red outline while removing any outline from the other two. The first t ...

How can I modify the orientation of the arrow and switch sides in a dropdown submenu?

I am working on creating a menu with dropdown-submenu functionality using CSS. .dropdown-menu { float:left; } .left-submenu { float: none; } .left-submenu > .dropdown-menu { border-radius: 6px 0px 6px 6px; left: auto; margin-lef ...

Enhance the color scheme of your collapsed or expanded Bootstrap NAV for mobile devices

Currently working on customizing the navbar using Bootstrap. I've been able to style it perfectly for both desktop and mobile devices in its initial state. The issue arises when attempting to style the navbar in its expanded and collapsed states on m ...

When using angular.less, the @import feature is functioning correctly but a 404 error is displayed in the

Currently, I am working on a project using AngularJS along with angular.less. To centralize all my constants, I have stored them in one .less file and imported it at the beginning of all my other less files using a relative path: @import "constants" Even ...

Ensuring the selected date matches any consecutive dates within the dates array in Angular

Imagine if 01/01/2022 is chosen from the input field, and my array of dates looks something like this: ['31/12/2021', '01/11/2021', '02/01/2022'...] In this scenario, when '31/12/2021' and '02/01/2022' are ...

Changing the background color of a PHP input based on the webpage being viewed - here's how!

I'm in the process of creating a website where each page will have its own unique background color. Additionally, I am using a PHP input for both the header and footer sections, which need to change their background colors based on the specific webpa ...

There seems to be an issue with the CSS header alignment as the logo is not properly positioned using a top margin of -20px

My goal is to create a header bar that includes an image, a title, and a menu car. I want the bar to be displayed after scrolling 50px down, and I also want the image to be positioned slightly above the wrapping div, showing a bit of it in the top 50px. Ri ...

Looking for assistance with CSS selectors for the following structure

I am currently working on locating the anchor element "a" that is nested inside a table with the class name table.ic-table-creditReportProduct table tr. I have attempted to find it, but my attempts have been unsuccessful so far. Any suggestions on where th ...

Leveraging functions with Ng-Repeat

I am currently dealing with two different arrays of objects. The first array contains a list of permissions groups, while the second array consists of user groups. My main goal is to compare the Group Owner (which is represented by ID 70) with the list of ...

How can we use jQuery to change the format of a

I'm working on a project where I want the calendar to display the date that the user picks. Right now, my "{{date}}" is in the format 2016-01-11, but it keeps showing one day before the selected date. I would like it to display as mm/dd/yyyy. I belie ...

When using Ruby and Rack on Heroku to serve a static site, the CSS styling may not be

Trying to deploy a static site consisting of HTML, CSS, font, and image files with Ruby Rack has been a bit challenging. While the HTML displays perfectly in Chrome when running it locally, the CSS assets do not seem to be loading or being applied to the H ...

Adding to a webpage's URL with PHP prior to rendering the content

Currently, I am investigating how to add a random query string at the end of a URL when someone visits my page for the first time. Let's say an individual goes to my website at www.example.com. If everything proceeds as planned, they will land on my i ...

Create a basic chart using JavaScript

I am looking to replicate a specific chart using JavaScript. The red point in the chart is variable. So far, I have attempted to create it using the flot library: var d3 = [[7,7]]; $.plot("#placeholder", [{ data: d3, points: { show: true } }], { ...