How to solve the diagonal submenu hover problem
Dropdown menus are a very common pattern around the web, their code is pretty straightforward:
- Use
position: relative
on the parent menu item. - Use
position: absolute
on submenu. - Toggle submenu visibility on parent hover.
However that doesn’t account for the fact that most users don’t move the cursor to the submenu on a straight line, most of the time they will move the cursor diagonally as it’s the shortest path to the content they’re trying to access.
The problem
The main problem with the “hover parent, toggle children” approach is that as soon as the cursor leaves the parent item then the submenu is hidden. This is a bigger issue with full width dropdowns because in some cases users will try to click on content on the furthest end of the submenu.
Luckily there’s a few ways to solve this issue:
1. Using javascript
We all know javascript solves everything and this is no exception, you can use a plugin like jQuery-menu-aim to help differentiate between a user trying hover over a dropdown item vs trying to navigate into a submenu’s contents.
The demos show Amazon-like vertical dropdowns but it also supports horizontal menus. It works quite well even though it hasn’t been updated in years but if you’re trying to keep bundle sizes small then maybe a CSS-only solution is a better alternative.
2. Using pseudo-elements
If the problem with the dropdowns hiding is the cursor leaving the parent item by accident then maybe we can extend the parent item to provide a larger margin for error.
The ::before
and ::after
pseudo-elements are part of an element content so they can be used to create a “safety net” below the top level items than will keep the dropdown open when hovered over.
The red stripped area is an ::after
pseudo element of the parent item which is only shown on hover and, since it sits on top of all top menu items, it will keep the menu open even when hovering outside the parent item boundaries. The background is just a visual aid, in real life it looks something like this:
It can work with vertical menus as well, however for this case the item’s length needs to be taken into account to create the safe area’s width, and even then it can get tricky to click on the top menu items in some circumstances.
You can play around with the sample code in Codepen and let me know what you think!
There’s probably a more accurate way of doing this but this seem to cover 99% of our use cases without major drawbacks so it’s a good option to keep in your CSS tricks arsenal.