flyingL123 flyingL123 - 6 months ago 30
HTML Question

CSS dropdown menu not functioning as expected on iPad

I have a CSS-only dropdown menu that functions as expected on desktop. On mobile Safari on an iPad, when one of the top-level navigation links is clicked, its dropdown menu shows briefly, but the link is followed, bringing the user to a new page.

I have been reading everything I can find about this and it seems like the default behavior is supposed to be that the iPad will treat the first tap as a hover, and not actually follow the link until there is a second tap. This is because the

:hover
style alters the
display
property of its submenu, so the device knows not to follow the link on the first tap.

I've seen this behavior working appropriately on other sites, and have even seen it working correctly on other parts of my website, but for some reason, it does not behave correctly with my CSS dropdown menu.

The menu can be seen on my site, https://www.storeyourboard.com. There is a horizontal menu listing category names near the top of the page. If you view this on an iPad, and tap on one of the menu items, for example "Surfboard", you will see that the iPad navigates to the Surfboard page, rather than displaying the dropdown menu on first tap. Strangely, there have been times that my tapping randomly behaves as expected, and the dropdown menu displays without navigating, but that has been rare, and I can't reproduce it consistently.

This is the relevant markup for the menu:

HTML

<ul class="mainNav-menu">
<li>
<a href="/sup-racks-bags/">SUP</a>
<div class="mainNav-submenu">
<ul class="mainNav-submenu-menu">
<!-- Submenu items here -->
</ul>
</div>
</li>
<li>
<a href="/surfboard-racks-bags/">Surfboard</a>
<div class="mainNav-submenu">
<ul class="mainNav-submenu-menu">
<!-- Submenu items here -->
</ul>
</div>
</li>
</ul>


CSS

.mainNav-submenu {
display: none;
position: absolute;
left: 0;
right: 0;
top: auto;
background-color: #8a8a8a;
z-index: 20;
padding: 1rem;
}

.mainNav-menu > li:hover .mainNav-submenu {
display: block;
}


I've seen some other posts saying that adding
onclick="return true"
to the menu links or the menu container will fix it, but this did not have any effect for me. I should also mention that I'm using fastclick.js on the site. I thought this could be causing the issue, but when I remove it, I see the exact same behavior.

I also added the code from this article to my site just to see if it would behave correctly, and it did. In other words, I added this small snippet of code to my site:

<style>
p {height: 100px;}

p span {
display: none;
}

p:hover span {
display: block;
}
</style>

<p>
<a href="/">Tap me</a>
<span>You tapped!</span>
</p>


This worked correctly (even with fastclick active). If I tapped on the link, the "You tapped" span showed, and if I tapped again, I navigated away.

I can not figure out why this same behavior is not working correctly for my navigation menu. Is it something in the way I have it marked up or styled? Does anyone have any idea? I'm not sure what else to do.

UPDATE

Thanks to Doc's answer below, I was able to come up with this solution:

.mainNav-menu > li > a {
pointer-events: none;
}

.mainNav-menu > li:hover > a {
pointer-events: all;
}


It's live on the site now and you can see it in action. I still don't know why this is necessary and why it didn't work originally, so if anyon has any ideas, please let me know.

Doc Doc
Answer

I don't know why tapping the a link causes it to be followed, but this should still solve the problem.


First, make it so that there is a regular piece of text on all of these tags, as well as the link. So keep

<a href="/surfboard-racks-bags/">Surfboard</a>

but also add

<p>Surfboard</p>

Make sure that both of these elements have the same content and style

Then, make the link have display: none by default, so its hidden. But when the div is hovered, make the link visible (with something like display: inline) and give the other non-link display: none. Ideally the p element should seamlessly be replaced by the a element, which should be styled the exact same, as if the a was there all along

For the desktop, when the user isn't hovering the div, there's no reason that the "link" part of the link needs to be active, so it's substituted for regular text. When the user is hovering the div, than the link shows up, so he/she can use it.

However, when an iOS user taps the div, he/she should trigger the :hover effect, but not the link; since the link wasn't visible when he/she tapped, it shouldn't be triggered. If the user still is clicking on the link, than add something like transition: display 0s 0.1s to the a and p elements, since the link might be shown too quickly

The only problem with this approach is that once the iOS user opens the dropdown, he/she can't close it by clicking on it again; that would trigger the link. But the user could click somewhere else and it should close