タッチ対応のブラウザーでホバーをシミュレートするにはどうすればよいですか?


120

次のようなHTMLを使用します。

<p>Some Text</p>

次に、このようないくつかのCSS:

p {
  color:black;
}

p:hover {
  color:red;
}

タッチ対応デバイスで長いタッチをホバーを複製するようにするにはどうすればよいですか?マークアップを変更したり、JSを使用したりできますが、これを行う簡単な方法は考えられません。


私は特にiPhone OSについて考えています。CSSアニメーションのデモで、多くの人にとって、クリックするのではなく、ホバーを使用して開始するのが簡単です。
リッチブラッドショー

回答:


172

はい、解決しました!CSSを少し変更し、JSを追加します。

jQueryを使用して簡単にする:

$(document).ready(function() {
    $('.hover').on('touchstart touchend', function(e) {
        e.preventDefault();
        $(this).toggleClass('hover_effect');
    });
});

英語:タッチを開始または終了するときに、クラスをhover_effectオンまたはオフにします。

次に、HTMLで、クラスホバーをこれで動作させたいものに追加します。CSSで、次のインスタンスを置き換えます。

element:hover {
    rule:properties;
}

element:hover, element.hover_effect {
    rule:properties;
}

さらに便利にするために、これをCSSにも追加します。

.hover {
-webkit-user-select: none;
-webkit-touch-callout: none;        
}

画像などをコピー/保存/選択するように求めるブラウザを停止します。

かんたん!


これは素晴らしい。私はかかわらず、domready機能を分割なぜならtoggle意志台無しユーザは、1つの要素に触れると(彼らは間違った項目に触れたとタッチをキャンセルしようとしている場合など)別にドラッグ場合
Jacksonkr

削除touchendpreventDefault()て自分のウェブサイトに表示しましたが、正常に機能しますが、ターゲットをタップしてもメニューが自動的に閉じません。
ДаниилПронин

また、ユーザーが他の場所をタップしたり、スクロールを開始したときに、このようなメニューを閉じる方法についてもアドバイスをお願いします。touchstart体に別のリスナーがいるかもしれないと思います(または同様の)が、もっと良い方法があるかどうか疑問に思いました。ありがとう!
ダリルヤング

2
スクロールジェスチャーを無視する方法はありますか?これはまさに私が必要としていることを実行しますが、この効果を持つコンテンツを上下にスクロールできなくなりました。
同じく陽気な

1
スクロールできるようにしたいのでpreventDefaultを削除しましたが、touchstartとtouchendのヒントに感謝します!神がこれを送るのは、すべてのブラウザで確実に機能する唯一の答えです。
Petraeus

54

親にタッチスタートをバインドするだけです。このようなものはうまくいきます:

$('body').on('touchstart', function() {});

関数では何もする必要がなく、空のままにしておきます。これは、タッチでホバーを取得するのに十分なので、タッチは:hoverのように動作し、:activeのようには動作しません。iOSの魔法。


2
このソリューションでは、2回目のタップでリンクを実行できますか?
samuelkobe

1
いいえ、最初のタッチでのクリックはまだトリガーされます。私はそれをテストしました。
ジャック

素晴らしいソリューション!早くて簡単。
ハンターターナー

41

これを試して:

<script>
document.addEventListener("touchstart", function(){}, true);
</script>

そしてあなたのCSSで:

element:hover, element:active {
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-user-select: none;
-webkit-touch-callout: none /*only to disable context menu on long press*/
}

このコードを使用すると、追加の.hoverクラスは必要ありません。


1
これは私にとってはうまくいきます。これをさらに助けるかもしれない他のいくつかのことは、JavaScriptを追加する代わりに、これを実行します:<body ontouchstart = "">次に、css:activeイベントに小さなタイマーを追加します:tr:active {background-color :#118aab; 遷移:すべての.2s線形。-webkit-tap-highlight-color:rgba(0,0,0,0); -webkit-user-select:なし。-webkit-タッチコールアウト:なし}
コージー

私のために働いた。ありがとう...唯一のこと-それは少し遅れます...つまり-押した後、即座に読み込まれません。
ローマンロセフ

fastclick.jsを使用してラグを削除する
Anselm

25

主な質問に答えるには、「タッチインタッチ対応のブラウザーでホバーをシミュレートするにはどうすればよいですか?」

(画面をタップして)要素を「クリック」できるようにhoverし、JavaScriptを使用してイベントをトリガーします。

var p = document.getElementsByTagName('p')[0];
p.onclick = function() {
 // Trigger the `hover` event on the paragraph
 p.onhover.call(p);
};

これはhover、デバイスにイベントがある限り、正常に機能します(通常は使用されませんが)。

更新:このテクニックをiPhoneでテストしたところ、問題なく動作するようです。ここで試してみてください:http : //jsfiddle.net/mathias/YS7ft/show/light/

代わりに「ロングタッチ」を使用してホバーをトリガーしたい場合は、上記のコードスニペットを開始点として使用して、タイマーなどを楽しんでください;)


そのonhover.call(p)ビットについては知りませんでした。ホバーオフはありません...
リッチブラッドショー

これを複数の要素と長いタッチでテストしましたか?ユーザーが指を画面上で動かし、各要素にホバースタイルを表示するという意味ですか?
Marcus、

すでにjQueryを使用している場合は、jQuery自体でホバーイベントを呼び出すだけでよいかもしれません。例:jQuery.hover(); ただし、APIがそれをサポートしているかどうかは不明です。
Kzqai

おっと、それは実際にjQueryを使用する上記の投稿により適切なコメントでした。申し訳ありません。
Kzqai

特別なスクリプトを作成したり、関数を呼び出したりする必要がありますか?それは私にとってはうまくいきますが、1ページだけで違いが何であるかわかりません。
Richard Young

13

さらに改善されたソリューション

最初はリッチブラッドショーのアプローチを採用しましたが、問題が発生し始めました。「touchstart」イベントでe.preventDefault()を実行すると、ページがスクロールしなくなり、長押ししてもオプションメニューを起動できず、ズームをダブルクリックしても実行を終了できません。

解決策としては、どのイベントが呼び出されているかを調べて、後のイベント'touchend'e.preventDefault()見つけるだけです。スクロールの「touchmove」「touchend」の前に来るため、デフォルトのままであり、「クリック」もモバイルに適用されるイベントチェーンの後に来るので防止されます。

// Binding to the '.static_parent' ensuring dynamic ajaxified content
$('.static_parent').on('touchstart touchend', '.link', function (e) {

    // If event is 'touchend' then...
    if (e.type == 'touchend') {
        // Ensuring we event prevent default in all major browsers
        e.preventDefault ? e.preventDefault() : e.returnValue = false;
    }

    // Add class responsible for :hover effect
    $(this).toggleClass('hover_effect');
});

ただし、オプションメニューが表示されると、クラスを切り替えるための「タッチエンド」が起動されなくなり、次回のホバー動作が逆になり、完全に混同されます。

次に、解決策は、再び、発生しているイベントを条件付きで見つけるか、単に別々のイベントを実行することであり、'touchstart'および'touchend'でそれぞれaddClass()およびremoveClass()を使用して、常に開始および終了することを保証します条件付きで決定するのではなく、それぞれ追加と削除を行います。最後に、削除コールバックを「focusout」イベントタイプにバインドし、次のように、リンクのホバークラスをクリアする責任を負い続けます。

$('.static_parent').on('touchstart', '.link', function (e) {
    $(this).addClass('hover_effect');
});

$('.static_parent').on('touchend focusout', '.link', function (e) {
    // Think double click zoom still fails here
    e.preventDefault ? e.preventDefault() : e.returnValue = false;
    $(this).removeClass('hover_effect');
});

注意:以前の2つのソリューションではまだいくつかのバグが発生しており、ダブルクリックズームも失敗します(テストされていません)。

Tidyとうまくいけばバグフリー(:)ではないJavascriptソリューション

次に、JavaScriptを使用して(.hoverクラスと疑似:hoverを混在させずに)、よりクリーンで整然としたレスポンシブなアプローチとして、ユニバーサル(モバイルおよびデスクトップ)の「クリック」イベントでajaxの動作を直接呼び出すことができる場所から、かなりよく答えられた質問を見つけました。そこから、いくつかのイベントコールバックが必然的に互いのイベントチェーンを変更することなく、タッチイベントとマウスイベントを混在させる方法を理解しました。方法は次のとおりです。

$('.static_parent').on('touchstart mouseenter', '.link', function (e) {
    $(this).addClass('hover_effect');
});

$('.static_parent').on('mouseleave touchmove click', '.link', function (e) {
    $(this).removeClass('hover_effect');

    // As it's the chain's last event we only prevent it from making HTTP request
    if (e.type == 'click') {
        e.preventDefault ? e.preventDefault() : e.returnValue = false;

        // Ajax behavior here!
    }
});

3

マウスhoverエフェクトはタッチデバイスでは実装できません。私は同じような状況で登場していたときsafari ios、私使用:active効果を作るためにCSSで。

すなわち。

p:active {
  color:red;
}

私の場合、その動作します。これは、JavaScriptを使用せずに使用できる場合にも当てはまります。試してみてください。


2

このコードを追加してから、クラス「tapHover」を、この方法で機能させたい要素に設定します。要素を初めてタップすると、疑似クラス ":hover"とクラス "tapped"が取得されます。クリックイベントは防止されます。2回目に同じ要素をタップすると、クリックイベントが発生します。

// Activate only in devices with touch screen
if('ontouchstart' in window)
{
    // this will make touch event add hover pseudoclass
    document.addEventListener('touchstart', function(e) {}, true);

    // modify click event
    document.addEventListener('click', function(e) {
        // get .tapHover element under cursor
        var el = jQuery(e.target).hasClass('tapHover')
            ? jQuery(e.target)
            : jQuery(e.target).closest('.tapHover');

        if(!el.length)
            return;

        // remove tapped class from old ones
        jQuery('.tapHover.tapped').each(function() {
            if(this != el.get(0))
                jQuery(this).removeClass('tapped');
        });

        if(!el.hasClass('tapped'))
        {
            // this is the first tap
            el.addClass('tapped');
            e.preventDefault();
            return false;
        }
        else
        {
            // second tap
            return true;
        }
    }, true);
}
.box {
	float:		left;
	
	display:	inline-block;
	margin:		50px 0 0 50px;
	width:		100px;
	height:		100px;
	overflow:	hidden;
	
	font-size:	20px;
	
	border:		solid 1px black;
}
.box.tapHover {
	background:	yellow;
}
.box.tapped {
	border:		solid 3px red;
}
.box:hover {
	background:	red;
}
<div class="box" onclick="this.innerHTML = Math.random().toFixed(5)"></div>
<div class="box tapHover" onclick="this.innerHTML = Math.random().toFixed(5)"></div>
<div class="box tapHover" onclick="this.innerHTML = Math.random().toFixed(5)"></div>


1

デバイス(またはブラウザー)固有のJSがなければ、あなたは運が悪いと確信しています。

編集:私があなたの質問を再読するまでそれを避けたいと思った。Mobile Safariの場合は、登録してネイティブUIView-sで実行できるのと同様のすべてのタッチイベントを取得できます。現在、ドキュメントが見つかりませんが、探します。


1

これを行う1つの方法は、タッチが開始したときにホバー効果を実行し、タッチが移動または終了したときにホバー効果を削除することです。

iPhoneについて触れたので、これはAppleが一般的にタッチハンドリングについて言わなければならないことです。


リンクの内容は今でも関連がありますか?
Flavien Volken 2017年

1

私の個人的な好みは、次のように:hoverスタイルを:focus州にも帰属させることです。

p {
    color: red;
}

p:hover, p:focus {
    color: blue;
}

次に、次のHTMLを使用します。

<p id="some-p-tag" tabindex="-1">WOOOO</p>

そして、次のJavaScript:

$("#some-p-tag").on("touchstart", function(e){
    e.preventDefault();
    var $elem = $(this);

    if($elem.is(":focus")) {
        //this can be registered as a "click" on a mobile device, as it's a double tap
        $elem.blur()
    }
    else {
        $elem.focus();
    }
});

1

解決済み2019-ホバーオンタッチ

今では、一般的にiosまたはtouchと一緒にホバーを使用しないことをお勧めします。以下のコードは、タッチが維持されている限り、他のiOSフライアウトなしでCSSを適用します。これを行う;

  1. jquery add:$( "p")。on( "touchstart"、function(e){$(this).focus(); e.preventDefault();});

  2. CSS:p:hoverをp:focusに置き換え、p:activeを追加

オプション;

  • jquery pセレクターを任意のクラスなどに置き換えます

  • 効果を維持するには、p:hoverも保持し、body {cursor:ponter;}を追加して、どこかをタップすると終了します

  • 同じコードでクリック&マウスオーバーイベントとタッチスタートを試してください(ただしテストされていません)

  • e.preventDefault();を削除します。ユーザーがコピーなどのiOSフライアウトを利用できるようにする

ノート

  • テキスト要素についてのみテストされ、iOSは入力などを異なる方法で処理する場合があります

  • SafariまたはChromeを使用したiphone XR ios 12.1.12、およびipad 3 ios 9.3.5でのみテストされています。


0

ネイティブJavaScriptとjQueryの組み合わせ:

var gFireEvent = function (oElem,sEvent) 
{
 try {
 if( typeof sEvent == 'string' && o.isDOM( oElem ))
 {
  var b = !!(document.createEvent),
     evt = b?document.createEvent("HTMLEvents"):document.createEventObject();
  if( b )    
  {  evt.initEvent(sEvent, true, true ); 
    return !oElem.dispatchEvent(evt);
  }
  return oElem.fireEvent('on'+sEvent,evt);
 }
 } catch(e) {}
 return false;
};


// Next you can do is (bIsMob etc you have to determine yourself):

   if( <<< bIsMob || bIsTab || bisTouch >>> )
   {
     $(document).on('mousedown', function(e)
     {
       gFireEvent(e.target,'mouseover' );
     }).on('mouseup', function(e)
     {
       gFireEvent(e.target,'mouseout' );
     });
   }

1
よくわからないがjqueryはjavacript
matpol

2
@matpol:jQueryはJavaScriptですが、JavaScriptはjQueryではありません。あなたのために私は「純粋な」という言葉、純粋なjavascriptを追加します。満足しましたか?
Codebeat 2013年

「純粋な」JavaScriptを使用せずにjqueryを使用することはできません。私が指摘するのは、SOに頻繁にアクセスする人の中にはこれを知らない人もいるからです。
matpol 2013年

5
ネイティブJavascriptとjQueryの混合、満足ですか?
Codebeat

0

私が見つけた最も簡単なソリューション::hover cssルールが含まれた<span>タグがいくつかありました。<a href = "javascript:void(0)">とvoilàに切り替えました。iOSのホバースタイルが機能し始めました。


0

CSSを使用することもできます。非表示のリンクにフォーカスとアクティブ(IE7以前の場合)を追加します。クラスmenuを持つdiv内のulメニューの例:

.menu ul ul {display:none; position:absolute; left:100%; top:0; padding:0;}
.menu ul ul ul {display:none; position:absolute; top:0; left:100%;}
.menu ul ul a, .menu ul ul a:focus, .menu ul ul a:active { width:170px; padding:4px 4%; background:#e77776; color:#fff; margin-left:-15px; }
.menu ul li:hover > ul { display:block; }
.menu ul li ul li {margin:0;}

それは遅く、テストされていない、うまくいくはずです;-)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.