I have a website with a two-level dropdown menu (it's not this one!). I want it to be slick, so I used CSS to only show the submenus when the user was hovering on the relevant parent menu item. This was great, until I realized people liked to access my website from their phones. The only way to reveal the submenus using a touch screen is to click the top menu item, but that will activate the link and change the page before you can find the link you want.
I looked at a few things, including doubletaptogo.js. They were either too complicated or didn't work (doubletaptogo.js fell into the latter category; I may have been able to get it to work if I rearchitected the site's entire theme to move the menu into a specific position).
Here is what I eventually came up with. Imagine a menu with this HTML:
<ul id="menu"> <li id="menu-1"> <a href="#">Item 1</a> <ul id="submenu1"> <li id="submenu1-1><a href="#">Submenu 1 Item</a></li> <li id="submenu1-2><a href="#">Submenu 1 Item</a></li> </ul></li> <li id="menu-2"> <a href="#">Item 2</a> <ul id="submenu2"> <li id="submenu2-1><a href="#">Submenu 2 Item</a></li> <li id="submenu2-2><a href="#">Submenu 2 Item</a></li> </ul></li> </ul>
My pre-existing CSS did this:
#menu li > ul { display: none; } #menu li:hover > ul { display: block; }
This is great; the submenus appear when you hover with this CSS alone. You need a bit more to make it nice, but then you can worry about phones.
To modify this to work with touch screens and Desktops (fairly) well, I added a javascript file with the following code (requires jQuery):
$(document).ready(function() { //set all top-level li tags to be unselected, in the view of this code $('#menu > li').attr('menu-selected', 'false'); //if you click a li tag (mobile or desktop), either add the menu-selected //attr OR do the default behaviour (go to the link) $('#menu-main-nav > li').click(function(e) { if($(this).attr('menu-selected') === 'true') { return true; //default behaviour -> open the link } e.preventDefault(); $('#menu-main-nav > li').attr('menu-selected', 'false'); $(this).attr('menu-selected', 'true'); return false; }); //emulate hover for desktop users $('#menu-main-nav > li').mouseenter(function(e) { $(this).attr('menu-selected', 'true'); }); $('#menu-main-nav > li').mouseleave(function(e) { $(this).attr('menu-selected', 'false'); }); });
Then you need to slightly adapt your CSS:
#menu li:hover > ul { display: none; /* override old behaviour */ } #menu li[menu-selected=true] > ul { display: block; }
This isn't super elegant or beautiful, but it is very easy to encapsulate into one file and put into an existing codebase. That's what I wanted, and it works well!