96

サイトに:hover(js なしで)展開する CSS メニューがいくつかあります。

これは、iDevices では半壊れた方法で機能します。たとえば、タップすると:hoverルールがアクティブになり、メニューが展開されますが、他の場所をタップしても削除されません:hover:hoverまた、 'ed'要素内にリンクがある場合は、リンクをアクティブにするために 2 回タップする必要があります (1 回目のタップでリンクがトリガーされ:hover、2 回目のタップでリンクがトリガーされます)。

touchstartイベントをバインドすることで、iPhone でうまく動作させることができました。

問題は、モバイル サファリが、イベントではなく:hoverCSS からルールをトリガーすることを選択する場合があることです。touchstart

cssですべてのルールを手動で無効にすると:hover、モバイルサファリがうまく機能するため、これが問題であることはわかっています(ただし、通常のブラウザーは明らかに機能しません)。

:hoverユーザーがモバイルサファリを使用しているときに、特定の要素のルールを動的に「キャンセル」する方法はありますか?

ここで iOS の動作を参照して比較してください: http://jsfiddle.net/74s35/3/ 注: 一部の css プロパティのみが 2 クリック動作をトリガーすることに注意してください。背景ではありません:赤。またはテキスト装飾: 下線;

4

16 に答える 16

76

iPhone/iPad Safari で ":hover" が予測できないことがわかりました。要素をタップすると、その要素が「:hover」になることがありますが、他の要素に移動することもあります。

とりあえずボディで「ノータッチ」の授業だけ。

<body class="yui3-skin-sam no-touch">
   ...
</body>

また、「.no-touch」の下に「:hover」を含むすべての CSS ルールがあります。

.no-touch my:hover{
   color: red;
}

ページのどこかに、本文からノータッチクラスを削除する JavaScript があります。

if ('ontouchstart' in document) {
    Y.one('body').removeClass('no-touch');
}

これは完璧に見えませんが、とにかく機能します。

于 2011-01-19T10:22:22.843 に答える
18

ブラウザ機能検出ライブラリModernizerには、タッチ イベントのチェックが含まれています。

デフォルトの動作は、検出された各機能のクラスを html 要素に適用することです。これらのクラスを使用して、ドキュメントのスタイルを設定できます。

タッチ イベントが有効になっていない場合、Modernizr は次のクラスを追加できますno-touch

<html class="no-touch">

次に、このクラスでホバー スタイルのスコープを設定します。

.no-touch a:hover { /* hover styles here */ }

カスタム Modernizr ビルドをダウンロードして、必要な数の機能検出を含めることができます。

適用できるいくつかのクラスの例を次に示します。

<html class="js no-touch postmessage history multiplebgs
             boxshadow opacity cssanimations csscolumns cssgradients
             csstransforms csstransitions fontface localstorage sessionstorage
             svg inlinesvg no-blobbuilder blob bloburls download formdata">
于 2013-01-29T23:54:35.203 に答える
18

一部のデバイス(他の人が言っているように)には、タッチイベントとマウスイベントの両方があります。たとえば、Microsoft Surface には、タッチ スクリーン、トラックパッド、およびスタイラスがあり、画面上でホバーすると実際にホバー イベントが発生します。

:hover「タッチ」イベントの存在に基づいて無効にするソリューションは、Surface ユーザー (および他の多くの同様のデバイス) にも影響します。多くの新しいラップトップはタッチであり、タッチ イベントに応答します。そのため、ホバリングを無効にすることは非常に悪い習慣です。

これは Safari のバグです。このひどい動作を正当化する理由はまったくありません。どうやら何年も前からある iOS Safari のバグのため、iOS 以外のブラウザを妨害することは拒否します。来週のiOS8でこれを修正してくれることを本当に願っていますが、それまでの間....

私の解決策

すでに Modernizr の使用を提案している人もいますが、Modernizr を使用すると、独自のテストを作成できます。ここで私が基本的に行っているのは、サポートするブラウザーのアイデアを:hoverModernizr テストに "抽象化" することです。これは、全体をハードコーディングすることなく、コード全体で使用できますif (iOS)

 Modernizr.addTest('workinghover', function ()
 {
      // Safari doesn't 'announce' to the world that it behaves badly with :hover
      // so we have to check the userAgent  
      return navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? false : true;
 });

するとcssはこんな感じに

html.workinghover .rollover:hover 
{
    // rollover css
}

iOS でのみ、このテストが失敗し、ロールオーバーが無効になります。

このような抽象化の最良の部分は、特定の android で壊れていることがわかった場合、または iOS9 で修正された場合は、テストを変更するだけでよいことです。

于 2014-09-14T19:45:11.900 に答える
16

FastClick ライブラリをページに追加すると、モバイル デバイス上のすべてのタップが (ユーザーがクリックした場所に関係なく) クリック イベントに変換されるため、モバイル デバイスでのホバーの問題も修正されるはずです。例としてフィドルを編集しました:http://jsfiddle.net/FvACN/8/

ページに fastclick.min.js ライブラリを含めて、次の方法でアクティブ化するだけです。

FastClick.attach(document.body);

副次的な利点として、モバイル デバイスが悩まされている 300 ミリ秒の onClick 遅延も解消されます。


FastClick を使用すると、サイトにとって重要な場合とそうでない場合がある、いくつかの小さな結果があります。

  1. ページのどこかをタップし、上にスクロールして下にスクロールし、最初に置いたのとまったく同じ位置で指を離すと、明らかにそうではないにもかかわらず、FastClick はそれを「クリック」と解釈します。少なくとも、私が現在使用している FastClick のバージョン (1.0.0) では、このように動作します。そのバージョン以降、誰かが問題を修正した可能性があります。
  2. FastClick は、誰かが「ダブルクリック」する機能を削除します。
于 2013-07-01T23:06:01.980 に答える
1

.css の JQuery バージョンでは、JQuery と次のスクリプトを含むすべてのホバー ルールに .no-touch .my-element:hover を使用します

function removeHoverState(){
    $("body").removeClass("no-touch");
}

次に、body タグに class="no-touch" ontouchstart="removeHoverState()" を追加します。

ontouchstart が起動するとすぐに、すべてのホバー状態のクラスが削除されます

于 2011-07-08T18:49:23.527 に答える
0

答えてくれた@Morgan Chengに感謝しますが、「touchstart」(@Timothy Perez answerから取得したコード)を取得するためにJS関数を少し変更しましたが、これにはjQuery 1.7+が必要です

  $(document).on({ 'touchstart' : function(){
      //do whatever you want here
    } });
于 2013-11-20T12:52:53.913 に答える
0

Zenexer から提供された応答を考えると、追加の HTML タグを必要としないパターンは次のとおりです。

jQuery('a').on('mouseover', function(event) {
    event.preventDefault();
    // Show and hide your drop down nav or other elem
});
jQuery('a').on('click', function(event) {
    if (jQuery(event.target).children('.dropdown').is(':visible') {
        // Hide your dropdown nav here to unstick
    }
});

このメソッドは、最初にマウスオーバーを開始し、2 番目にクリックを開始します。

于 2014-06-03T05:58:15.983 に答える
0

タッチが利用できないときにホバー効果だけを持たせる代わりに、タッチイベントを処理するためのシステムを作成し、それで問題が解決しました。最初に、「タップ」(「クリック」に相当) イベントをテストするためのオブジェクトを定義しました。

touchTester = 
{
    touchStarted: false
   ,moveLimit:    5
   ,moveCount:    null
   ,isSupported:  'ontouchend' in document

   ,isTap: function(event)
   {
      if (!this.isSupported) {
         return true;
      }

      switch (event.originalEvent.type) {
         case 'touchstart':
            this.touchStarted = true;
            this.moveCount    = 0;
            return false;
         case 'touchmove':
            this.moveCount++;
            this.touchStarted = (this.moveCount <= this.moveLimit);
            return false;
         case 'touchend':
            var isTap         = this.touchStarted;
            this.touchStarted = false;
            return isTap;
         default:
            return true;
      }
   }
};

次に、イベント ハンドラーで次のようなことを行います。

$('#nav').on('click touchstart touchmove touchend', 'ul > li > a'
            ,function handleClick(event) {
               if (!touchTester.isTap(event)) {
                  return true;
               }

               // touch was click or touch equivalent
               // nromal handling goes here.
            });
于 2012-06-21T01:50:14.520 に答える
-12

これを配置するコードは次のとおりです

// a function to parse the user agent string; useful for 
// detecting lots of browsers, not just the iPad.
function checkUserAgent(vs) {
    var pattern = new RegExp(vs, 'i');
    return !!pattern.test(navigator.userAgent);
}
if ( checkUserAgent('iPad') ) {
    // iPad specific stuff here
}
于 2010-06-09T08:38:07.100 に答える