タッチデバイスで:hover cssスタイルを削除/無視する方法


141

:hoverユーザーがタッチデバイス経由で当社のWebサイトにアクセスした場合、すべてのCSS宣言を無視したいと思います。ので、:hoverCSSは意味がない、と要素がフォーカスを失うまで、それは固執する可能性があるので、それもクリック/タップにタブレットトリガ場合は、それを邪魔することができます。正直なところ、なぜタッチデバイスが:hover最初にトリガーの必要性を感じるのかはわかりませんが、これは現実であり、この問題も現実です。

a:hover {
   color:blue;
   border-color:green;
   // etc. > ignore all at once for touch devices
}

それで、(どのように):hover宣言したタッチデバイスのすべてのCSS 宣言を一度に(それぞれを知る必要なく)削除/無視できますか?



1
私は、表示デバイスがモバイルであるかどうかを発見し、それに基づいてさまざまな変更を加えた正しいスタイルシートを使用するphpソリューションでこれを回避します。それでもあなたの質問に答えることはできません。@mediaクエリを使用することもできますが、携帯電話やタブレットの解像度がフルHDの場合でも、その動作は保証されません。
TomFirth 2014年

回答:


170

tl; drこれを使用:https : //jsfiddle.net/57tmy8j3/

なぜ、または他にどんなオプションがあるのか​​興味があるなら、読み進めてください。

Quick'n'dirty-J​​Sを使用してホバースタイルを削除

:hoverJavaScript を使用して含まれているすべてのCSSルールを削除できます。これには、CSSに触れる必要がなく、古いブラウザーと互換性があるという利点があります。

function hasTouch() {
  return 'ontouchstart' in document.documentElement
         || navigator.maxTouchPoints > 0
         || navigator.msMaxTouchPoints > 0;
}

if (hasTouch()) { // remove all the :hover stylesheets
  try { // prevent exception on browsers not supporting DOM styleSheets properly
    for (var si in document.styleSheets) {
      var styleSheet = document.styleSheets[si];
      if (!styleSheet.rules) continue;

      for (var ri = styleSheet.rules.length - 1; ri >= 0; ri--) {
        if (!styleSheet.rules[ri].selectorText) continue;

        if (styleSheet.rules[ri].selectorText.match(':hover')) {
          styleSheet.deleteRule(ri);
        }
      }
    }
  } catch (ex) {}
}

制限:スタイルシートは同じドメインでホストする必要があります(つまり、CDNはありません)。UXを損なう、SurfaceやiPad Proなどの混合マウスとタッチデバイスのホバーを無効にします。

CSSのみ-メディアクエリを使用する

すべての:hoverルールを@mediaブロックに配置します。

@media (hover: hover) {
  a:hover { color: blue; }
}

または、ホバールールをすべてオーバーライドします(古いブラウザーと互換性があります)。

a:hover { color: blue; }

@media (hover: none) {
  a:hover { color: inherit; }
}

制限:WebViewを使用する場合、iOS 9.0以降、Chrome for AndroidまたはAndroid 5.0以降でのみ機能します。hover: hover古いブラウザのホバー効果を壊しhover: none、以前に定義されたすべてのCSSルールを上書きする必要があります。どちらも、マウスとタッチの混合デバイスと互換性がありません

最も堅牢-JSを介してタッチを検出し、CSS:hoverルールを付加

このメソッドでは、すべてのホバールールの前にを付ける必要がありますbody.hasHover。(または任意のクラス名)

body.hasHover a:hover { color: blue; }

hasHoverクラスを使用して添加することができるhasTouch()最初の例から。

if (!hasTouch()) document.body.className += ' hasHover'

ただし、これには、混合タッチデバイスで前の例と同じ欠点があり、これが究極のソリューションになります。マウスカーソルが移動するたびにホバー効果を有効にし、タッチが検出されるたびにホバー効果を無効にします。

function watchForHover() {
  // lastTouchTime is used for ignoring emulated mousemove events
  let lastTouchTime = 0

  function enableHover() {
    if (new Date() - lastTouchTime < 500) return
    document.body.classList.add('hasHover')
  }

  function disableHover() {
    document.body.classList.remove('hasHover')
  }

  function updateLastTouchTime() {
    lastTouchTime = new Date()
  }

  document.addEventListener('touchstart', updateLastTouchTime, true)
  document.addEventListener('touchstart', disableHover, true)
  document.addEventListener('mousemove', enableHover, true)

  enableHover()
}

watchForHover()

これは基本的にどのブラウザでも機能し、必要に応じてホバースタイルを有効または無効にします。

これが完全な例です-モダン:https : //jsfiddle.net/57tmy8j3/
レガシー(古いブラウザで使用):https : //jsfiddle.net/dkz17jc5/19/


ありがとうございました!ただ1つのコメント:?document.styleSheetsを使用するのではなく、存在するかどうかを最初に確認する方が良い try/catchでしょう。
Simon Ferndriger、2015年

1
try/catch同じ起源のポリシーまたはIEでの不安定なサポートのためにdeleteRuleが機能しないなど、奇妙なエラーが表示される場合に備えて使用しました(これを反映するようにコメントを編集しました)。しかし、そうです、ほとんどの場合、単純なチェックで十分です。
ブレード

1
Firefoxを含むデスクトップブラウザは「notouch」を引き起こさないことに言及する価値があります。彼らはタッチイベントの理解を報告します。
Harry B

3
このソリューションは、マウスでホバーが機能するがタッチイベントでは機能しない混合デバイスでは機能しません
nbar

2
@Haneevそれはあなたの特定のケースではありませんが、ほとんどのケースで正しいです。ルールを機能させると、コードが非常に複雑になり、答えを理解するのが難しくなります。ルールを分割するか、いずれにせよより堅牢な2番目のソリューションを使用することをお勧めします。ただし、最初のソリューションを複雑にせずに改善できる場合は、編集を提案することは大歓迎です。
ブレード

43

救助へのポインターの適応

これはしばらく触れられていないので、以下を使用できます。

a:link {
   color: red;
}

a:hover {
   color:blue;
}

@media (hover: none) {
   a:link {
      color: red;
   }
}

デスクトップブラウザーと電話ブラウザーの両方でこのデモをご覧ください。最新のタッチデバイスでサポートされています

:Surface PCの主要な入力(機能)はマウスであるため、分離された(タブレット)画面であっても、青いリンクになることに注意してください。ブラウザーは、常にデフォルトで最も正確な入力の機能を使用します(すべきです)。


ありがとう、これは便利でしょう!ただし、モバイルモードのChromeで試してみましたが、うまくいきませんでした。「タップ」
すると、

1
@SimonFerndrigerこれはChrome開発ツールの制限です。実際のタッチ専用デバイスでリンクを開いてみてください。
Jason T Featheringham 2017

1
iPad Chrome / SafariとOS X Chrome / Safariで完全に連携します。ありがとう!最後に、このような小さな視覚的な問題に対して必要なエレガントなソリューションです。
rakaloof

3
iOS 11を実行している実際のiPhone 6Sでこれを試したところ、リンクが青くなりました。
Lukas Petr

1
Android 8.1.0およびChrome 68.0.3440.91を実行するNexus 5Xでもこれを試しました。リンクが青くなった。
トレビンエイブリィ

12

私は同じ問題(Samsungモバイルブラウザーの場合)に遭遇したため、この質問に出くわしました。

カルサルの回答のおかげで、私が試したモバイルブラウザーで認識されているように見えるため、事実上すべてのデスクトップブラウザーを除外すると思われるものが見つかりました(コンパイルされた表のスクリーンショットを参照:CSSポインター機能検出表)。

MDN web docsは

ポインターCSS @media機能を使用して、ユーザーの主要な入力メカニズムがポインティングデバイスであるかどうかに基づいてスタイルを適用できます。

私が発見したのはそのポインタです。粗いというのは、添付の表にあるすべてのデスクトップブラウザーには不明ですが、同じ表にあるすべてのモバイルブラウザーでは認識されるものです。他のすべてのポインタキーワード値は一貫性のない結果をもたらすため、これは最も効果的な選択のようです。

したがって、Calsalで説明したようにメディアクエリを作成できますが、少し変更されます。逆のロジックを使用して、すべてのタッチデバイスを除外します。

Sassミックスイン:

@mixin hover-supported {    
    /* 
     * https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer 
     * coarse: The primary input mechanism includes a pointing device of limited accuracy.
     */
    @media not all and (pointer: coarse) {
        &:hover {
            @content;
        }
    }
}

a {
    color:green;
    border-color:blue;

    @include hover-supported() {
        color:blue;
        border-color:green;
    }
}

コンパイルされたCSS:

a {
  color: green;
  border-color: blue;
}
@media not all and (pointer: coarse) {
  a:hover {
    color: blue;
    border-color: green;
  }
}

問題を調査した後に作成した要点にも記載されています。 Codepen実証研究用の。

更新:この更新を書いている時点(2018-08-23)で、@ DmitriPavlutinによって指摘されたように、この手法はFirefoxデスクトップでは機能しないようです。


表(コンパイルされたとき)によれば、@ DmitriPavlutinに感謝しますが、もう一度検討することもできます。
ProgrammerPer

@DmitriPavlutinあなたは確かに正しいです。回答が更新されます
ProgrammerPer

1
排他的タッチデバイスで使用した場合、Firefoxデスクトップでは機能しないということですか?それは私が試したすべてのものとうまくいきます。
FuzzeeLowgeek

@FuzzeeLowgeekいいね!前回チェックしたのは2018-08-23だったので、これが確実に確認できれば、回答をもう一度更新できますか?
ProgrammerPer

9

Jasonの回答によれば、純粋なcssメディアクエリでのホバーをサポートしないデバイスのみに対応できます。同様の質問での moogalの回答のように、ホバーをサポートするデバイスのみに対処することもできます@media not all and (hover: none)。奇妙に見えますが、機能します。

私はこれを使いやすくするためにSassミックスインを作りました:

@mixin hover-supported {
    @media not all and (hover: none) {
        &:hover {
            @content;
        }
    }
}

アップデート2019-05-15:CSSでターゲットにできるすべての異なるデバイスを通過する、Mediumのこの記事をお勧めします。基本的には、これらのメディアルールを組み合わせたものであり、特定のターゲットに対してそれらを組み合わせます。

@media (hover: hover) {
    /* Device that can hover (desktops) */
}
@media (hover: none) {
    /* Device that can not hover with ease */
}
@media (pointer: coarse) {
    /* Device with limited pointing accuracy (touch) */
}
@media (pointer: fine) {
    /* Device with accurate pointing (desktop, stylus-based) */
}
@media (pointer: none) {
    /* Device with no pointing */
}

特定のターゲットの例:

@media (hover: none) and (pointer: coarse) {
    /* Smartphones and touchscreens */
}

@media (hover: hover) and (pointer: fine) {
    /* Desktops with mouse */
}

私はミックスインが大好きです。これは、ホバーミックスインを使用して、それをサポートするデバイスのみをターゲットにする方法です。

@mixin on-hover {
    @media (hover: hover) and (pointer: fine) {
        &:hover {
            @content;
        }
    }
}

button {
    @include on-hover {
        color: blue;
    }
}

それはまったく機能しません。ホバーがあります:ホバーがサポートするミックスインのメディアクエリに何もありませんか?あなたはポインタが必要です:ここでの他の答えに従って粗い。
アランNienhuis

試してみたことがありますか、それとも奇妙に見えるので機能しないと言っていますか?それが私が「奇妙に見える」と書いた理由です。そして、それはポインタなしで私のために機能します:粗いです。
カルサル

私のOnePlus 5T(ChromeとFirefixの両方)では、これに対するCSSのアプローチに一貫性のない結果がありました。これはiOSでは問題なく動作しましたが、OnePlusでは動作しませんでした。
エニー

6

現在、同様の問題を扱っています。

すぐに発生する主なオプションは2つあります。(1)ユーザー文字列のチェック、または(2)別のURLを使用して個別のモバイルページを維持し、ユーザーに適切なものを選択してもらいます。

  1. PHPやRubyなどのインターネットダクトテープ言語を使用できる場合は、ページをリクエストしているデバイスのユーザー文字列を確認し<link rel="mobile.css" />、通常のスタイルではなく同じコンテンツを提供するだけで済みます。

ユーザー文字列には、ブラウザ、レンダラー、オペレーティングシステムなどに関する識別情報があります。「タッチ」デバイスと非タッチデバイスのどちらを使用するかは、あなた次第です。この情報はどこかにあり、システムにマッピングできる場合があります。

A. 古いブラウザ無視することが許可されている場合、通常のモバイル以外のCSSに単一のルールを追加する必要がありますつまり、EDIT:Erkです。いくつかの実験を行った後、私もちょうど審美的効果が無効であることを原因に加えてのWebKitブラウザでリンクをたどるする機能を無効にしたルールの下に発見-参照http://jsfiddle.net/3nkcdeao/を
そのように、あなたが持っているでしょうモバイルケースのルールを変更する方法については、ここで示すよりも少し厳しくする必要がありますが、それは役に立つ出発点になる場合があります。

* { 
    pointer-events: none !important; /* only use !important if you have to */
}

補足として、現在、親でポインターイベントを無効にしてから子で明示的に有効にすると、子要素が入ると、親のホバー効果が再びアクティブになります:hover
見るhttp://jsfiddle.net/38Lookhp/5/を

B.レガシーWebレンダラーをサポートしている場合、中に特別なスタイルを設定するルールを削除するという線に沿ってもう少し作業を行う必要があります:hover。すべての人の時間を節約するために、モバイルバージョンを作成するために標準のスタイルシートで実行する自動コピー+ sed ingコマンドを作成することができます。これにより、標準コードを記述/更新:hoverし、モバイルバージョンのページで使用するスタイルルールを削除することができます。

  1. (I)または、web サイト.comに加えて、モバイルデバイス用のm.website.comがあることをユーザーに知らせます。サブドメイン化が最も一般的な方法ですが、モバイルユーザーが変更されたページにアクセスできるように、特定の他の予測可能なURLの変更を加えることもできます。その段階では、サイトの別の部分に移動するたびにURLを変更する必要がないようにする必要があります。

ここでも、スタイルシートに1つまたは2つのルールを追加するか、sedまたは同様のユーティリティを使用して、やや複雑な処理を強制することができます。CSSを変更するのではなく、jsまたはサーバー言語を使用してモバイルユーザーの迷惑なことを行う要素にdiv:not(.disruptive):hover {...追加class="disruptive"するようなスタイルルールに適用するのはおそらく最も簡単です。

  1. (II)最初の2つを実際に組み合わせることができ、(ユーザーが間違ったバージョンのページに移動した疑いがある場合は)モバイルタイプのディスプレイに切り替えたり、モバイルタイプのディスプレイから切り替えたりすることを提案できます。ユーザーがフロップすることができます。すでに述べたように、@ mediaクエリは、訪問に何が使用されているかを判断する際に使用するのにも役立ちます。

  2. (III)「タッチ」デバイスとそうでないデバイスが分かれば、jQueryソリューションを使用する場合、タッチスクリーンデバイスでCSSホバーが無視されないことが役立つ場合があります。


pointer-events-すごい!それはまさに私が探していたものです、本当にありがとう!
Simon Ferndriger 2014年

1
@SimonFerndrigerさて、私はそれが今後役立つことを願っています。現在のところ、<a>リンクはにアクセスできない可能性があることに注意してくださいpointer-events:none。運が良ければ、それは後で変わるでしょうpointer-events:navigation-only。そうでなければ、CSS 3.xか4.0+が同じかそれ以上になるでしょう。
SeldomNeedy 2014年

6

これを試して:

@media (hover:<s>on-demand</s>) {
    button:hover {
        background-color: #color-when-NOT-touch-device;
    }
}

更新:残念ながら、W3Cはこのプロパティを仕様から削除しました(https://github.com/w3c/csswg-drafts/commit/2078b46218f7462735bb0b5107c9a3e84fb4c4b1)。


これは確かに問題を解決します。これまで聞いたことがありません。これはどのブラウザバージョンで動作するはずですか?
Simon Ferndriger


良い...それは幅広いブラウザをサポートしていません。
Giacomo Paita

カッコいい!そのような便利な解決策をありがとう。W3C標準に追加されることを願っています。
GProst


5

あなたは使用することができますModernizr JS(この参照StackOverflowの答えを)、またはカスタムJS関数を作ります:

function is_touch_device() {
 return 'ontouchstart' in window        // works on most browsers 
  || navigator.maxTouchPoints;       // works on IE10/11 and Surface
};

if ( is_touch_device() ) {
  $('html').addClass('touch');
} else {
  $('html').addClass('no-touch');
} 

ブラウザーでのタッチイベントのサポート検出し、次のようにクラスでCSS要素をトラバースする通常のプロパティを割り当てますhtml.no-touch

html.touch a {
    width: 480px;
}

/* FOR THE DESKTOP, SET THE HOVER STATE */
html.no-touch a:hover {
   width: auto;
   color:blue;
   border-color:green;
}

これは@bladeでも提案されていますが、htmlタグの代わりにタグを使用bodyすると、読みやすくなる場合があります。それが実際に私が現在使用しているソリューションです。とにかくありがとうございました。
Simon Ferndriger 16

1

それは私にとって役に立ちました:リンク

function hoverTouchUnstick() {
    // Check if the device supports touch events
    if('ontouchstart' in document.documentElement) {
        // Loop through each stylesheet
        for(var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) {
            var sheet = document.styleSheets[sheetI];
            // Verify if cssRules exists in sheet
            if(sheet.cssRules) {
                // Loop through each rule in sheet
                for(var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) {
                    var rule = sheet.cssRules[ruleI];
                    // Verify rule has selector text
                    if(rule.selectorText) {
                        // Replace hover psuedo-class with active psuedo-class
                        rule.selectorText = rule.selectorText.replace(":hover", ":active");
                    }
                }
            }
        }
    }
}

1

これも可能な回避策ですが、CSSを確認して、 .no-touch確認して、ホバースタイルの前にクラスます。

JavaScript:

if (!("ontouchstart" in document.documentElement)) {
document.documentElement.className += " no-touch";
}

CSSの例:

<style>
p span {
    display: none;
}

.no-touch p:hover span {
    display: inline;
}
</style>
<p><a href="/">Tap me</a><span>You tapped!</span></p>

ソース

Psしかし、私たちは覚えておかなければなりません。市場にはますます多くのタッチデバイスが登場しており、同時にマウス入力もサポートしています。


0

これはまだ完全な解決策ではないかもしれません(jQueryを使用している場合もあります)が、おそらくそれは取り組むべき方向性/コンセプトです。つまり、デフォルトで:hover css状態を非アクティブにし、ドキュメントのどこかにmousemoveイベントが検出された場合にアクティブにします。もちろん、誰かがjsを無効にした場合、これは機能しません。このようにそれを行うことに対して他に何が反対するでしょうか?

多分このように:

CSS:

/* will only work if html has class "mousedetected" */
html.mousedetected a:hover {
   color:blue;
   border-color:green;
}

jQuery:

/* adds "mousedetected" class to html element if mouse moves (which should never happen on touch-only devices shouldn’t it?) */
$("body").mousemove( function() {
    $("html").addClass("mousedetected");
});

1
1つの問題は、実際には、タッチデバイスで何かをクリックすると.mousemove()になることです。
larsがupstructに2016

1
そして、おそらくこのイベントをノンストップでトリガーして、パフォーマンスに影響を与えます。これが機能する場合は、使用する方がよいでしょう$('body').one.('mousemove', ...)
Simon Ferndriger 2017

0

これを試してください(この例ではbackgroundとbackground-colorを使用しています):

var ClickEventType = ((document.ontouchstart !== null) ? 'click' : 'touchstart');

if (ClickEventType == 'touchstart') {
            $('a').each(function() { // save original..
                var back_color = $(this).css('background-color');
                var background = $(this).css('background');
                $(this).attr('data-back_color', back_color);
                $(this).attr('data-background', background);
            });

            $('a').on('touchend', function(e) { // overwrite with original style..
                var background = $(this).attr('data-background');
                var back_color = $(this).attr('data-back_color');
                if (back_color != undefined) {
                    $(this).css({'background-color': back_color});
                }
                if (background != undefined) {
                    $(this).css({'background': background});
                }
            }).on('touchstart', function(e) { // clear added stlye="" elements..
                $(this).css({'background': '', 'background-color': ''});
            });
}

css:

a {
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

0

汚い方法...エレガントではありませんが、あなたを救うことができる最も簡単な方法。

ホバーを特徴付けるものをすべて削除します。

.your-class:hover:before {
  color: blue;
  background: linear-gradient(to bottom, rgba(231,56,39,0) 0%, #aaaaaa 100%);
}

@media all and (min-width:320px) and (max-width: 960px) {
    .your-class:hover:before {
    color: black;
    background: transparent;
  }
}

0

あなたがアンドロイドにタッチ/タップしたときの問題であり、div全体が青い透明色で覆われている場合!次に、単に変更する必要があります

CURSOR:POINTER; カーソルへ:デフォルト;

mediaQueryを使用して携帯電話/タブレットで非表示にします。

これは私にとってはうまくいきます。


-1

この簡単な2019 jqueryソリューションを試してみてください。

  1. このプラグインをヘッドに追加します:

    src = "https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"

  2. これをjsに追加:

    $( "*")。on( "touchend"、function(e){$(this).focus();}); //すべての要素に適用

  3. これに対する推奨されるバリエーションは次のとおりです。

    $( ":input、:checkbox、")。on( "touchend"、function(e){(this).focus);}); //要素を指定

    $( "*")。on( "click、touchend"、function(e){$(this).focus();}); //クリックイベントを含める

    css:body {cursor:pointer; //どこでもタッチしてフォーカスを終了します

ノート

  • プラグインをbootstrap.jsの前に配置して、ツールチップに影響を与えないようにします
  • SafariまたはChromeを使用したiphone XR ios 12.1.12、およびipad 3 ios 9.3.5でのみテストされています。

参照:

https://code.jquery.com/ui/

https://api.jquery.com/category/selectors/jquery-selector-extensions/


2
2019では、jQueryを使用する必要はありません。WebAPIはかなり強力で、すべての主要な機能をサポートしています。
acme

はい... 2019年のjQuery?いくつかのフラッシュはどうですか?へへへ。
remed.io
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.