Keyboard Accessible Dropdown Menu

Keyboard Accessible Dropdown Menu


When browsing the web via a keyboard, tabbing through page links is the primary way to navigate around a page quickly. However, this creates a problem with traditional dropdown navigation menus. When tabbing through, you can’t access the dropdown items since they typically require a mouse hover.

To address this issue, you have a couple of options. One approach is to go the Bootstrap route and require a click to display the dropdown (equivalent to pressing the return key on a keyboard). Alternatively, you can utilize a combination of CSS Hover state for mouse users and employ some JavaScript hackery to make the dropdown display itself when the parent item receives focus state, mimicking a mouseover interaction. Both approaches necessitate additional client-side JavaScript to ensure full accessibility.

However, thanks to a new CSS pseudo-class, we can eliminate the need for this extra JavaScript and simplify the entire process using :focus-within.

The Markup

If you’ve been coding HTML navigation menus for a while now, you’ll know the basic technique already. Your markup should look something like this:

<nav>
  <ul>
    <li>
      <a href="/page">Page link</a>
      <ul>
        <li><a href="/page/subpage">I'm a dropdown item</a></li>
      </ul>
    </li>
    <li>
      <a href="/page">Another link</a>
    </li>
  </ul>
</nav>

The Styles

And then use some basic styles to make it look like a menu and show the dropdown on hover like this:

nav ul {
  display: flex;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
nav ul li {
  position: relative;
}
nav ul li ul {
  position: absolute;
  top: 100%;
  left: 0;
  visibility: hidden;
}
nav ul li:hover ul {
  visibility: visible;
}

The New Good Good

This is where you can skip the entire JavaScript portion of this process and add just a single extra line to your hover styles:

nav ul li:hover ul,
nav ul li:focus-within ul { {
	visibility: visible;
}

Typically this is when you learn that there isn’t enough browser support for this new sparkly web thing you just learned about and can’t use it — But wait! It’s actually quite good and all modern browsers have supported it for at least a couple years now. 🕺

It’s nice when new standards come out that simplify things that used to be a lot more complex and all the browsers hop on board. 🥰

Other Recent Posts