Dropdown menus are a very common pattern around the web, their code is pretty straightforward:
position: relativeon the parent menu item.
position: absoluteon 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 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:
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.
::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.