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

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!
Very cool examples
Interesting stuff! So many different ways to approach this problem.
Mo’ content, mo’ problems, though I’d have to argue that having an enormous tree of submenus is probably bad UX in itself.
Never once thought of pseudo elements for this, great idea!
It seems like combining your existing narrow corridor trick (the red rectangles) with the (un)hover intent technique would make a pretty slick fix. Use larger, more forgiving pseudo-elements (or an overlapping margin on the submenu) with say a .1s transition. That way you can clip the corners on the way to the submenu, but if you actually want the next element down the lag is minimal.
Could you try to use CSS triangles (e.g. border trickery) to turn your invisible square affordances into triangles? It might interfere with other menu items just a little less. You could probably even make the triangles horizontally longer whilst still minimising the interference.
The thing with CSS triangles is that they aren’t really triangles, they are squares where 2-3 borders of them are transparent so they just look like triangles.
It might be possible to use little SVG chunks though (heavier in the DOM). Or possibly even better, CSS
clip-path: polygon()
to get a triangular area.You could rotate an element though… that would retain the correlation between the mouse appearing to be over an element and actually being over that element. Use some JS black magic to figure out what size rectangle and what angle of rotation would be needed so that one point is where the mouse activated the drop-down menu, and the two neighboring points are positioned at the nearest top and bottom corners (for horizontally-opening menus) or left and right corners (for vertically-opening menus) of the drop-down menu (illustration).
I’ve been using the transition delay technique for a long time and I think it works great.
Spot on! Easily the best approach IMO.
Thank you for mentioning this. I’ve also been using transition delay for this. Here is an example that implements transition delay on a mega menu. Notice how when them menu is open, you can take a diagonal mouse path to the sub links. http://sparkexperience.com/projects/mclaren/member/?for=individualgroup
I´m with Matt. The transition delay is in my opinion the most elegant way to avoid navigation problems.
Nice article. Glad I’m not the only one to suffer from drop-down usability frustrations. Some nice solutions here.
Good article, I’ve used both the psuedo element and delay techniques in the past.
Things are not so simple I feel for touch events.
We could just trigger dropdowns with a click event, but what if the user really wanted to go to the landing page for that whole category?
What I tend to go with is to always have a landing page which has navigation within to the sub pages so touch devices can still navigate to the desired location.
For screens below the breakpoint of the navigation the ‘mobile’ menu allows you to trigger sub-menus or navigate to the landing page depending on what part of the menu item is clicked. The issue with this not being the case on larger screens is I wouldn’t want to loose the mouse interaction that you get on desktop.
Simple. First click expands dropdown and adds a class like “clicked”.
Second click leads to linktarget if element has class “clicked”.
gergfegrege: That could work but I feel it could make for pretty poor ux, it’s been driven into web users not to double click on the web. very few of the users would know that its possible to navigate to the parent page unless you gave some kind of visual cue.
I agree with you about double-clicks.
I’ve dealt with this on a few sites that have multiple levels of navigation. When the mobile menu is shown and a sub-nav is present, I reproduce the parent nav item and insert it as a child link. When you click on a menu item, the sub nav is shown and the sub-menu’s first child is a link to that landing (or parent) page. If there are no children to begin with, I don’t do this and leave it link to the page. If you do this, you then need an icon or some way to show there are sub-menus.
This codepen uses this method. This also uses a back navigational item to navigate between the different nav levels.
This is great. I am always using superfish for navigation, these tricks will all work with it. Thanks for the share.
As a bit of background, I remember Bruce Tognazzini describing this as a problem solved by Apple’s late lamented Human Interface Group in the 80s. The solution was very similar to the one implemented in Amazon’s drop-downs.
Wow! Really nice post! Thank You
I do like the way you have done the codepen dropdowns Chris. Simple and effective. The only issue I have, and it’s a small, personal point: when you hover over the pseudo-elements the hover styles on the link item disappear so you can’t see that the current item is still active.
I think the only way to achieve this though would be to either change the
:hover
state to apply to.has-submenu
, or duplicate the:hover
on the.has-submenu
such as:http://jsfiddle.net/ahallicks/cLofnrcd/
Based on your ideas i created the following script to allow nested bootstrap nav menus. They are fully responsive and does not need corridors or something else.
https://github.com/dsentker/BootstrapSubnav
have a look at voronoi. user interface algorithms -> https://www.youtube.com/watch?v=90NsjKvz9Ns
I always set a timer. It’s the shortest, fastest, and the easiest solution. I know that it requires JavaScript, but honestly how do you surf the web without JavaScript these days. Also, with a timer I can customize relationships between moments. Entrance vs exit, dropdown levels, and button to button can be different based on time. The other thing a I’m using a timer for is menu reactions on mobile devices.
Idiot proofing the web, one selector at a time. Well done Chris, I’ve sought out solutions for this in the past and you’ve finally come up with one that really works, and works well.
Nice Idea
Seriously though, what IS Libero?
That is so weird, I was working on a three level, side-by-side menu yesterday and had this exact issue. Thanks!
Regarding keyboard access, we set up a pretty decent keyboard tracker for Nichols College. The code is on Github too.
Nice one! Never thought about integrating pseudo-elements and lag in the whole menu picture before! Thanks!
Well this was my take on the problem back in 2014:
http://playground.idesigned.cz/projects/hoverintentmegamenu/
I also used pseudo-elements. But with rotation and animations to cover more space. This solutions is somewhere between your “basic CSS aproach” and “Amazons fancy javascript triangle”.
I can’t tell you if the solution works for users, because project for which I developed this snippet isn’t yet in production.
All you need is to add a timeout to your trigger, then clear the timeout:
Got to agree with Tim Rourke on this, nested menu’s generally mean something is going horribly wrong… Working on an e-commerce site for a huge american eyewear retailer, I honesty believe that if you do sub-menu’s from a top-menu link your copy needs work; or your site is overly complex, hindering marketing performance.
Autocompletes, filters, tags, a nice side-bar, or side-scrolling breadcrumb-ish menu’s (similar to the old flash ones), always work better than drop-downs and often have none of the issues around performance and caching that huge menu tree’s can have; so you can fix the menu’s while also making the site faster!