Making Dropdowns Work on Touch Devices like Tablets

I swear this used to be default functionality, but lately on my iPad, some websites–when viewed on tablets–don’t allow you to click a top-level navigation element to show the dropdown. Instead, they just jump to whatever the URL of the top level navigation’s `<a>` href is.

If you’re running into this, here’s how to fix it with some jQuery. First, the code below assumes you have navigation HTML like so:

<ul class="nav">
<li><a href="/">Home</a></li>
<li><a href="/about/">About</a>
<ul class="sub-menu">
<li><a href="/company/">Company</a></li>
<li><a href="/contact/">Contact</a></li>
</ul>
</li>
</ul>

That’s a pretty standard setup, and should work well with many a WordPress default navigation.

Here’s the jQuery:

function is_touch_device() {
return 'ontouchstart' in window // for standard browsers
|| 'onmsgesturechange' in window; // for IE10
}
if (is_touch_device()) {
$('ul.nav > li').each(function(){
if ( $(this).children('ul.sub-menu').length > 0 ) {
$(this).addClass('touch-top-level');
}
});
$( "li.touch-top-level > a" ).one( "click", function(e) {
e.preventDefault();
});
};

Let’s review quickly for those who want to know what’s actually happening.

function is_touch_device() creates a function that simply tests for touch events.

if (is_touch_device()) { runs the function. If the browser indicates that yes, it does have touch functionality, this returns true and the rest of the code is executed.

$('ul.nav > li').each(function(){ Here we check for all li elements that belong immediately to the ul.nav – which is what > does in this line. So it won’t detect an li in our .sub-menu lists, since those aren’t “immediately” children of ul.nav.

if ( $(this).children('ul.sub-menu').length > 0 ) { checks to see if the li we just checked has a sub-menu, and if so, we add a CSS class of touch-top-level via $(this).addClass('touch-top-level'); to make it easier to work with.

$( "li.touch-top-level > a" ).one( "click", function(e) { – there the .one tells jQuery to only do this action once per element it applies to.

e.preventDefault(); this basically says “Don’t follow the link” in this case.

If they click it a second time, though, it will follow the link since we had set one.

Have fun!

Up Next: How to Get aggregateRating Schema / Google Structured Data for Woocommerce Reviews