web-dev-qa-db-ja.com

iOS Safariでクリックすると、タップした場所の下の要素で「ホバー状態」がトリガーされます

IOS Safari(iOSのバージョンは問題ではないと思いますが、<div>がある場合はiOS(Safari)11)でテストしています:hover効果を持つ要素の上に配置され、<div>をクリックすると消えるイベントがあり、要素がDOMから削除された後、「下」リンクにホバー効果が適用されます。

私が話していることのアニメーションGIFについては、以下を参照してください。

iOS click through

ボタンの背後にあるリンクが見えるように、ボタンにシースルーの背景を指定しました。リンクが配置されていないスポットでボタンをタップしても、リンク(つまりSome link)が青のままで変化しない赤のホバー状態に。

ただし、divがDOMから削除された後、偶然リンク上のであるスポットでdivをタップすると、リンクにホバー状態が適用されます。

これらのそれぞれが正しくon.clickイベント(アラートウィンドウ)をトリガーした後にリンクをクリックします。

はありませんAndroid on Chrome(以下の例を参照)でこの問題を確認してください:

Android click through working

以下に、私が使用したサンプルHTML/CSS/JSもあります。セットアップは非常に簡単です。

IOSを同じように動作させたいAndroid Chromeする:DOMからすぐに削除される要素をクリックするnot直後の要素に対して:hover状態をトリガーすべきではありません。

document.addEventListener("DOMContentLoaded", function ready() {
  var button = document.querySelector(".button");
  button.addEventListener("click", function() {
    button.parentNode.removeChild(button);
  });
  
  document.querySelector('a').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>
17
romellem

ホバーを無効にするオプションがある場合は、ちょっとしたハックでそれを行うことができます。

最初にこの行を「DOMContentLoaded」イベントハンドラーに追加します。

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

.can-hoverクラスをHTMLドキュメントの本文に追加します。

次に、これに一致するようにa:hoverルールを編集します

あなたのCSSルール:

a:hover {
  color: red;
}

する必要があります:

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

これにより、タッチスクリーンを備えたデバイスがホバースタイルをアンカーに適用できなくなります。

7
Milan Jaric

メディアクエリを使用して:hover機能をテストしようとしましたか?

https://drafts.c​​sswg.org/mediaqueries/#hover を参照してください

4
Josh Palmeri

...ホバー可能な項目のリストをスワイプした場合でも、これはiOSで意図された動作であることがはっきりとわかります。

回避しようとしているのがホバー効果だけである場合、ここに私がすることを示します。 JS関数を使用してデバイスを取得し、bodyタグにクラスを適用し、必要に応じてホバー効果を削除します。

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
}
4
scooterlord

これはiOSに固有の設計決定のようです(または、多分Chrome方法が設計決定であり、彼らによって行われます;わかりません)。iOSは「マウス-タッチオンリーのデバイスでもWebページに「マウスオーバー」をスローします。ユーザーがマウスを持っているかどうかを判断する方法を見つけようとしています。正しく機能するものは見つかりません。

Windowsもタッチで同じことをしていると思います。ポイントにタッチすると、マウスポインターが効果的に移動してクリックし、マウスポインターが残ります。

これが契約違反になる場合は、デザインを変更する必要がある場合があります。

1
Joseph Hansen

これは、Safariで意図した動作のようです。 Appleの documentation は、シングルフィンガータップがマウスイベントとして処理されることを示しており、タップ中に発生するイベントを示しています。タップの先頭にはmouseoverがありますが、mouseoutは他の何かをクリックしたときにのみトリガーされます。これは、次のタップまでポインターが同じ場所にとどまることをSafariが想定していることを意味します。つまり、下の要素がホバー状態にあることは意味があります。

AndroidのChromeと、WindowsのChromeとFirefox(Appleデバイスがありません)でコードを試しました。 3つすべての場合で、マウスを使用して(リンク上で)<div>をクリックすると、マウスを離す前にリンクからカーソルを離さない限り、リンクにホバースタイルが適用されます。タッチスクリーンで指で<div>をタップすると、リンクがホバースタイルになりません。

FirefoxとChromeはタッチとマウスで互いに一貫しているように見えますが、Safariは(設計上)タッチスクリーンをマウスとして扱うようです:タッチプレスに対してChromeおよびFirefoxは、マウスのクリックに対して実行します。

これは、修正または回避する必要があるバグだとは思いません。すべてのユーザーが特定のハードウェア/ブラウザーの組み合わせを使用することがわかっている場合を除き、おそらく、マウス、タッチスクリーン、またはその両方を同時に使用できる可能性について計画する必要があります。これらすべての場合に機能するUIを設計します。私のWindowsラップトップとAndroidタブレットには両方ともマウスパッドとタッチスクリーンがあり、時々Android電話でUSB OTGマウスを使用します。

また、Chrome、IEおよびEdgeで動作する Pointer Events API を見ることができます( pointer-events CSSプロパティと混同しないでください) @erierによる言及)。 APIはCSSではなくイベントを処理するため、これはスタイリングを正しくするのに直接役立ちませんが、ブラウザーがさまざまなタイプの入力デバイスに一貫して反応するようにする努力を示しています。

1
JRI

同様の問題がありましたが、要素が削除される直前にポインターイベントnoneを追加し、要素が削除された後に再び設定することで解決しました。

document.addEventListener("DOMContentLoaded", function ready() {
  var button = document.querySelector(".button");
  button.addEventListener("click", function() {
    document.querySelector('a').classList.add("no-click");
    button.parentNode.removeChild(button);
    setTimeout(function() {
        document.querySelector('a').classList.remove("no-click");
    },1);
  });
  
  document.querySelector('a').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;
}
.no-click {
    pointer-events: none;
}
<a href="#">Some link</a>
<div class="button">Click me!</div>
1
marmite

これが実稼働コードで機能するかどうかはわかりませんが、この例では必要です。

ホバールールをクラスに吐き出し、DOMからザッピングした後、このクラスをボタン削除コールバックのリンクに適用できます。

それでもうまくいかない場合は、onmouseoverコールバックにクラスを追加できます。これは、ボタンが削除された後、(該当する場合)終了してリンクを再入力した後にのみ機能します。

それはすべて少しハックですが、どちらのブラウザー/ OSにも合うように動作を調整することができます。

0
allnodcoms

このハックは機能すると思います。

クラスでホバーを無効にする必要があり、上のdivがクリックされたときに、マウスの移動時にホバーブロッククラスを削除するイベントリスナーを追加します。

document.addEventListener("DOMContentLoaded", function ready() {
  var button = document.querySelector(".button");
  button.addEventListener("click", function() {
    button.parentNode.removeChild(button);
    var body = document.querySelector("body");
    body.addEventListener("mousemove", function() {
            var someLink = document.querySelector(".some-link");
            someLink.classList.remove("no-hover");
        });
  });
  
  document.querySelector('a').addEventListener("click", function() {
    window.alert('clicked!');
  });
});
a:link    { color: blue }
a:visited { color: blue }
a:hover   { color: red }
a:active  { color: green }

a.no-hover:hover { color: blue }

.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="#" class="some-link no-hover">Some link</a>
<div class="button">Click me!</div>
0
Joseph Hansen

ポインターイベントを使用すると、ここで役立つ場合があります。

document.addEventListener("DOMContentLoaded", function ready() {
  var button = document.querySelector(".button");
  button.addEventListener("click", function() {
    button.parentNode.removeChild(button);
  });
  
  document.querySelector('a').addEventListener("click", function() {
    window.alert('clicked!');
  });
});
a {pointer-events: none;}
a:link    { color: blue; pointer-events: auto; }
a:visited { color: blue }
a:hover   { color: red; pointer-events: auto; }
a:active  { color: green; pointer-events: auto; }

.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>
0
erier

新しいメディアクエリメソッドを試して、ユーザーのプライマリ入力メカニズムが要素の上に移動できるかどうかをテストします。

@media (hover) {
  // Your hover effects
  a:hover {
    color: red;
  }
}

ドキュメント: ホバー-CSS:カスケードスタイルシート| MDN

0
HarryMoore

これはブラウザの問題です。ホバー状態は、あってもなくてもどこにでも存在します。

.no-touchのクラスをボディに追加し、それらのみをスタイルします。

if (!("ontouchstart" in document.documentElement)) {
    document.body.classList.add('no-touch')
}

ここにすべてがあります

if (!("ontouchstart" in document.documentElement)) {
    document.body.classList.add('no-touch')
}
document.addEventListener("DOMContentLoaded", function ready() {
  var button = document.querySelector(".button");
  button.addEventListener("click", function(e) {
    button.parentNode.removeChild(button);
  });
  
  document.querySelector('a').addEventListener("click", function() {
    window.alert('clicked!');
  });
});
a:link    { color: blue }
a:visited { color: blue }
.no-touch 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>

これはあなたが探している答えではないかもしれませんが、AndroidとiOSの間で確実に一貫性を保つでしょう。

0
Joao Lopes