Dropdown Menus with More Forgiving Mouse Movement Paths

Avatar of Chris Coyier
Chris Coyier on (Updated on )

📣 Freelancers, Developers, and Part-Time Agency Owners: Kickstart Your Own Digital Agency with UACADEMY Launch by UGURUS 📣

This is a fairly old UX concept that I haven’t heard talked about in a while, but is still relevant in the case of multi-level dropdown menus. A fine-grained pointer like a mouse sometimes has to travel through pretty narrow corridors to accurately get where it needs to in a dropdown menu. It’s easy to screw up (have the mouse pointer leave the path) and be penalized by having it close up on you. Perhaps we can make that less frustrating.

Many dropdowns are designed such that when the right area isn’t in :hover, or a mouseleave or mouseout occurs, the submenu where the desired menu item is may close on you.
You can get to the menu item you want, but there are some narrow passages along the way.

A Basic CSS Approach

Dropdown menus are typically designed such that a submenu is revealed through CSS on a :hover of a parent element. Or on a mouseenter / mouseover in JavaScript and a state change. So the trick is to try and prevent any of those events from happening too easily. Widen up the corridors, as it were.

The whole reason I got to thinking about this is because the corridors were mighty narrow for our submenus in the main dropdown at CodePen. To widen them up at the choke point, I added a couple of pseudo-elements to the submenu. If the mouse goes over those, nothing happens, it’s just like the mouse is within the submenu as normal.

The red there is just to demonstrate where those pseudo-elements are positioned.

This is a super lightweight technique requiring only CSS, which I like. The slight danger is that you can cover up a decent amount of adjacent menu items, which could mean a user hovering over a legit menu item and not being able to click it. I imagine in a lot of cases they just move the mouse a little and it works, but it’s definitely a balancing act between too small and too big.

The history of this goes back to 2005 and a classic Position is Everything demo:

And potentially a Thierry Koblentz demo.

Widening CSS Boundaries

John Gardner created an approach where all the menus have extra space around them which provide the forgiving hover-offs:

Looks like this was deleted from the internet, sorry! There are lots of CSS dropdown menus on CodePen you can explore.

(Un)hover intent

Have you heard of “hover intent”? It’s this concept where you don’t trigger a response right away to mouse location events. You wait a split second, that way you can be sure the user wanted a reaction. It’s like intentional lag. It’s used in situations where the UI might be too twitchy without it.

The opposite of that we could call unhover intent. Like we react to a hover event immediately, but don’t react to a hover off for a little bit. In CSS, you could do something like:

.submenu {
  visibility: hidden;
  transition: 0.2s 1s; /* delay of 1 seconds on hover off */
}
.parent:hover .submenu {
  visibility: visible;
  transition-delay: 0s; /* react immediately on hover */
}

Note we are using visibility here, which is transitionable, rather than display, which is not (weirdly enough).

JavaScript is certainly capable of unhover intent as well. You’d approach it kind of like a debounce, where you wouldn’t call the functions that do the closing unless some time has passed. That could be done with a setTimeout that you clear if the mouse comes back on. This is overly simplistic, but:

var timer;

$(".parent").on("mouseover", function() {
  clearTimeout(timer);
  openSubmenu();
}).on("mouseleave", function() {
  timer = setTimeout(
    closeSubmenu
  , 1000);
});

function openSubmenu() {
  $(".submenu").addClass("open");
}
function closeSubmenu() {
  $(".submenu").removeClass("open");
}

Neither of these unhover demos dealt with the corridor problem by expanding the size, they dealt with it by forgiving a quick miss in mouse location.

Avoid the narrow corridor

There is no rule that submenu dropdowns need to go out to the side. If they open up directly below, the corridor remains wide. Here’s an example of that by Timothy M. LeBlanc:

Get fancy with a JavaScript-built triangle

There is a great post from a few years ago by Ben Kames on this subject. He was checking out how snappy the Amazon.com dropdown menus were, compared to other dropdowns that use delay tactics to handle the usability. The magic turned out to be math! If the mouse traveled at a reasonable angle toward the newly-opened submenu, it wouldn’t trigger the other menu items. Visual aid:

Ben turned it into a jQuery plugin that you can demo.

He’s also very right about this:

I’m sure this problem was solved years and years ago, forgotten, rediscovered, solved again, forgotten, rediscovered, solved again.

That’s a sad truth about lots of things in our industry.

Jon Neal took a stab at removing the jQuery dependency and improving the math with “barycentric coordinates”:

Alex Popov wrote in saying that he took a crack at this demo and improved its functionality. I didn’t have time to re-load it all in my brain to figure out the functional differences, but here’s a link to Alex’s version if your deep into all this and are looking at the possibilities.

Other Concerns

I think a wise person once said:

“Sometimes visitors to your website will have a mouse and sometimes they won’t.”

So, hopefully your dropdowns work with touch as well. You certainly can make them work! You can also make the call if you want to bundle all code together for efficiency, or if some kind of feature detection is in order to load different scripts and styles as needed (or a combo of both).

Keyboard accessibility is another classic concern with dropdown menus. I just didn’t want to leave you with the idea that helping mouse movement is all you need to do for good dropdown UX. There is always something to improve!

Other Examples

https://twitter.com/hakimel/status/1132932935399673857