In the world of web design and development, dropdown navigations or menus are a very common feature in pretty much any kinds of website because they are intuitive and not that difficult to code. However, they can be quite troublesome for users of touch-screen devices who cannot perform a proper hover interaction to expand the child panels of a dropdown navigation.
A simple tap (click) can be used to produce a hover effect. However, it won’t work properly on hyperlinks with URL. On some mobile browsers, hover can be emulated by a long touch on the hyperlink but this can also produce unwanted results such as opening a context menu or highlighting the text.
Consider this typical Suckerfish-style HTML structure:
<ul id="mainmenu"> <li><a href="about.html">About</a> <ul> <li><a href="about.html">Overview</a></li> <li><a href="news.html">News</a> <ul> <li><a href="news.html">Latest</a></li> <li><a href="archive.html">Archive</a></li> </ul> </li> </ul> </li> </ul>
Users using the touchscreen devices would not be able to access the sub-menus by a simple tap because both About and News has a URL that will simply redirect the page.
The workaround here is when a touch-screen browser is detected, we disable the URL in the hyperlinks dynamically via Javascript either by changing the location to “#” or by preventing the default action. Conveniently enough, the code for detecting touch-screen browsers can be borrowed from the awesome Modernizr.js library, in just three lines.
function is_touch_device() { return !!('ontouchstart' in window); }
What is left now is just to write the JS code that will go through the dropdown menu HTML and modify the <a> tag accordingly if it has a sub-menu. In jQuery, this can be written as follows:
$(document).ready(function() { /* If mobile browser, prevent click on parent nav item from redirecting to URL */ if(is_touch_device()) { $('#mainmenu li > ul').each(function (index, elem) { /* Option 1: Use this to modify the href on the <a> to # */ $(elem).prev('a').attr('href' ,'#'); /* OR Option 2: Use this to keep the href on the <a> intact but prevent the default action */ $(elem).prev('a').click(function(event) { event.preventDefault(); }); }); } });
If you have a dropdown menu with only one level of children, the code can be simplified further by modifying the jQuery selector and eliminating the “each” loop.
$(document).ready(function() { /* If mobile browser, prevent click on parent nav item from redirecting to URL */ if(is_touch_device()) { /* Option 1: Use this to modify the href on the <a> to # */ $('#mainmenu > li > a').attr('href' ,'#'); /* OR Option 2: Use this to keep the href on the <a> intact but prevent the default action */ $('#mainmenu > li > a').click(function(event) { event.preventDefault(); }); } });
The choice of using between Option 1 and Option 2 depends entirely on your application. If for instance you have additional JS events or interactions attached to the <a> tag of the dropdown menu, Option 2 might be useless because event.preventDefault(); might prevent those interactions from happening.
As always, I am happy to hear any other methods you might have out there to make hover interaction less miserable for touch screen users. Have a nice day!