Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A click in iOS Safari triggers a "hover state" on element underneath where you tapped

On iOS Safari 11, if I have a <div> positioned over an element that has a :hover effect, and the <div> has an event that makes it disappear when clicked, then my link "underneath" gets the hover effect applied after the element is removed from the DOM.

See below for an animated GIF of what I'm talking about:

iOS click through

I've given the button a see-through background so you can see the link behind it. When I tap the button in on a spot where the link is not located, the link (i.e. Some link) stays blue and does not change to its hover state of red.

However, when I tap the div in a spot that happens to be directly over the link, after the div is removed from the DOM, the link gets its hover state applied.

Clicking the link after each of these correctly triggers its on.click event (an alert window).

I do not see this issue on android on Chrome (see example below):

Android click through working

Below you'll also find the sample HTML/CSS/JS I used; the setup is pretty simple.

I'd like to have iOS act in the same way Android Chrome does: that is, clicking on an element that is immediately removed from the DOM should not trigger a :hover state for an element immediately behind it.

var button = document.querySelector(".button");
button.addEventListener("click", function() {
  button.parentNode.removeChild(button);
});

var link = document.querySelector('a');
link.addEventListener("click", function() {
  window.alert('clicked!');
});
a:link    { color: blue }
a:visited { color: blue }
a:hover   { color: red }
a:active  { color: green }

.button {
    background: rgba(100, 0, 0, .4);
    position: absolute;
  
    top: 2px;
    left: 2px;
    z-index: 1;

    width: 100px;
    height: 100px;
    line-height: 100px;

    text-align: center;
    border-radius: 5px;
}

.button:hover {
    background: rgba(0, 100, 0, .4);
    cursor: pointer;
}
<a href="#">Some link</a>
<div class="button">Click me!</div>
like image 769
romellem Avatar asked Dec 13 '17 21:12

romellem


3 Answers

If you have option to disable hover then you can do that with bit of hack.

First add this line in "DOMContentLoaded" event handler.

var canHover = !(matchMedia('(hover: none)').matches);
if (canHover) {
  document.body.classList.add('can-hover');
}

It will add .can-hover class to body of your html document.

Then just edit a:hover rule to match this instead

your css rule:

a:hover {
  color: red;
}

should be:

.can-hover a:hover {
  color: red;
}

this should prevent devices with touch screen to apply hover style to any anchor.

like image 55
Milan Jaric Avatar answered Oct 29 '22 15:10

Milan Jaric


Have you tried using a media query to test for :hover capability?

See https://drafts.csswg.org/mediaqueries/#hover

like image 32
Josh Palmeri Avatar answered Oct 29 '22 16:10

Josh Palmeri


...it can be clearly seen that this is the intended behavior on iOS even when swiping on a list of hover-able items.

If what you are trying to avoid is just the hover effect, here's what I would do. I would get the device using a JS function, apply a class on the body tag and remove any hover effects as needed.

Javascript:

function isAppleDevice() {
  return (
    (navigator.userAgent.toLowerCase().indexOf("ipad") > -1) ||
    (navigator.userAgent.toLowerCase().indexOf("iphone") > -1) ||
    (navigator.userAgent.toLowerCase().indexOf("ipod") > -1)
   );
}
if (isAppleDevice() {
  $('body').addClass('is_apple')
}

CSS:

.is_apple a:hover {
  // same styling as not hovering
}
like image 44
scooterlord Avatar answered Oct 29 '22 15:10

scooterlord