Deaktivieren Sie Hover-Effekte in mobilen Browsern


113

Ich schreibe eine Website, die sowohl von Desktops als auch von Tablets verwendet werden soll. Wenn es von einem Desktop aus besucht wird, sollen die anklickbaren Bereiche des Bildschirms mit :hoverEffekten (unterschiedliche Hintergrundfarben usw.) beleuchtet werden. Bei einem Tablet gibt es keine Maus, daher möchte ich keine Hover-Effekte.

Das Problem ist, wenn ich auf etwas auf dem Tablet tippe, hat der Browser offensichtlich eine Art "unsichtbaren Mauszeiger", der sich an die Stelle bewegt, auf die ich getippt habe, und ihn dann dort belässt - also leuchtet das Ding, auf das ich gerade getippt habe, mit einem auf Hover-Effekt, bis ich auf etwas anderes tippe.

Wie kann ich die Hover-Effekte erzielen, wenn ich die Maus verwende, sie jedoch unterdrücken, wenn ich den Touchscreen verwende?

Falls jemand daran gedacht hat, es vorzuschlagen, möchte ich kein User-Agent-Sniffing verwenden. Das gleiche Gerät könnte sowohl einen Touchscreen als auch eine Maus haben (vielleicht nicht so häufig heute, aber viel mehr in Zukunft). Ich interessiere mich nicht für das Gerät, ich interessiere mich dafür, wie es derzeit verwendet wird: Maus oder Touchscreen.

Ich habe bereits versucht , die Einhaken touchstart, touchmoveund touchendEreignisse und ruft preventDefault()auf allen von ihnen, die nicht unterdrückt die „unsichtbare Maus - Cursor“ einen Teil der Zeit; Wenn ich jedoch schnell zwischen zwei verschiedenen Elementen hin und her tippe, bewegt sich nach ein paar Fingertipps der "Mauszeiger" und die Hover-Effekte leuchten trotzdem auf - es ist, als würde ich preventDefaultnicht immer geehrt. Ich werde Sie nicht mit den Details langweilen, es sei denn, dies ist notwendig - ich bin mir nicht einmal sicher, ob dies der richtige Ansatz ist. Wenn jemand eine einfachere Lösung hat, bin ich ganz Ohr.


Bearbeiten: Dies kann mit Moor-Standard-CSS reproduziert werden :hover, aber hier ist eine kurze Repro als Referenz.

<style>
  .box { border: 1px solid black; width: 150px; height: 150px; }
  .box:hover { background: blue; }
</style>
<div class="box"></div>
<div class="box"></div>

Wenn Sie mit der Maus über eines der Felder fahren, wird ein blauer Hintergrund angezeigt, den ich möchte. Wenn Sie jedoch auf eines der Felder tippen, wird auch ein blauer Hintergrund angezeigt, was ich verhindern möchte.

Ich habe auch eine Probe geschrieben hier , dass die oben tut und auch Haken jQuery Mausereignisse. Sie können damit sehen, dass Tap-Ereignisse ebenfalls ausgelöst werden mouseenter, mousemoveund mouseleave.


7
@Blender, hast du die Frage gelesen? Ich habe bereits erklärt, warum das Schnüffeln von Benutzeragenten eine schlechte Wahl ist.
Joe White

Hey Joe, hast du eine Lösung dafür gefunden?
Ismatjon

Ich habe nach dieser Art von Frage gesucht und bin froh, dass ich sie gefunden habe!
agpt

Siehe auch diese Frage, die sich mit dem Deaktivieren des Hover auf allen Touch-fähigen Geräten befasst, nicht nur auf Mobilgeräten: stackoverflow.com/questions/23885255/…
Blade

Antworten:


83

Ich gehe von Ihrer Frage aus, dass Ihr Hover-Effekt den Inhalt Ihrer Seite verändert. In diesem Fall rate ich:

  • Fügen Sie Hover-Effekte auf touchstartund hinzu mouseenter.
  • Entfernen Sie Hover - Effekte auf mouseleave, touchmoveund click.

Alternativ können Sie Ihre Seite so bearbeiten, dass sich der Inhalt nicht ändert.

Hintergrund

Um eine Maus zu simulieren, lösen Browser wie Webkit Mobile die folgenden Ereignisse aus, wenn ein Benutzer einen Finger auf dem Touchscreen (wie dem iPad) berührt und loslässt (Quelle: Touch And Mouse auf html5rocks.com):

  1. touchstart
  2. touchmove
  3. touchend
  4. 300 ms Verzögerung, wobei der Browser sicherstellt, dass es sich um ein einzelnes Tippen handelt, nicht um ein doppeltes Tippen
  5. mouseover
  6. mouseenter
    • Hinweis : Wenn ein mouseover, mouseenteroder mousemoveEreignis den Seiteninhalt ändert, werden die folgenden Ereignisse nie gebrannt.
  7. mousemove
  8. mousedown
  9. mouseup
  10. click

Es scheint nicht möglich zu sein, den Webbrowser einfach anzuweisen, die Mausereignisse zu überspringen.

Was noch schlimmer ist: Wenn ein Mouseover-Ereignis den Seiteninhalt ändert, wird das Klickereignis niemals ausgelöst, wie im Safari Web Content Guide - Behandeln von Ereignissen erläutert , insbesondere in Abbildung 6.4 unter Ein-Finger-Ereignisse . Was genau eine "Inhaltsänderung" ist, hängt vom Browser und der Version ab. Ich habe festgestellt, dass für iOS 7.0 eine Änderung der Hintergrundfarbe keine Inhaltsänderung ist (oder nicht mehr?).

Lösung erklärt

Um es noch einmal zusammenzufassen:

  • Fügen Sie Hover-Effekte auf touchstartund hinzu mouseenter.
  • Entfernen Sie Hover - Effekte auf mouseleave, touchmoveund click.

Beachten Sie, dass keine Aktion aktiviert ist touchend!

Dies funktioniert eindeutig für Mausereignisse: mouseenterund mouseleave(leicht verbesserte Versionen von mouseoverund mouseout) werden ausgelöst und fügen den Hover hinzu und entfernen ihn.

Wenn der Benutzer tatsächlich einen clickLink hat, wird auch der Hover-Effekt entfernt. Dadurch wird sichergestellt, dass es entfernt wird, wenn der Benutzer die Zurück-Taste im Webbrowser drückt.

Dies funktioniert auch bei Touch-Ereignissen: Beim Touchstart wird der Hover-Effekt hinzugefügt. Es wird am Touchend nicht entfernt. Es wird am erneut hinzugefügt mouseenter, und da dies keine Inhaltsänderungen verursacht (es wurde bereits hinzugefügt), wird das clickEreignis ebenfalls ausgelöst und der Link wird verfolgt, ohne dass der Benutzer erneut klicken muss!

Die Verzögerung von 300 ms, die ein Browser zwischen einem touchstartEreignis hat und clickdie tatsächlich gut genutzt wird, da der Hover-Effekt in dieser kurzen Zeit angezeigt wird.

Wenn der Benutzer beschließt, den Klick abzubrechen, erfolgt eine Bewegung des Fingers wie gewohnt. Normalerweise ist dies ein Problem, da kein mouseleaveEreignis ausgelöst wird und der Hover-Effekt bestehen bleibt. Zum Glück kann dies leicht behoben werden, indem der Hover-Effekt auf entfernt wird touchmove.

Das ist es!

Beachten Sie, dass es möglich ist, die Verzögerung von 300 ms zu entfernen, z. B. mithilfe der FastClick-Bibliothek . Dies ist jedoch für diese Frage nicht zulässig .

Alternativlösungen

Ich habe die folgenden Probleme mit den folgenden Alternativen gefunden:

  • Browsererkennung: Extrem fehleranfällig. Angenommen, ein Gerät verfügt entweder über eine Maus oder eine Berührung, während eine Kombination aus beiden immer häufiger wird, wenn sich die Anzeige von Berührungen vermehrt.
  • CSS-Medienerkennung: Die einzige CSS-Lösung, die mir bekannt ist. Immer noch fehleranfällig und geht immer noch davon aus, dass ein Gerät entweder Maus oder Touch hat, während beide möglich sind.
  • Emulieren Sie das Klickereignis in touchend: Dies folgt falsch dem Link, selbst wenn der Benutzer nur scrollen oder zoomen wollte, ohne die Absicht, tatsächlich auf den Link zu klicken.
  • Verwenden Sie eine Variable, um Mausereignisse zu unterdrücken: Hiermit wird eine Variable festgelegt touchend, die als if-Bedingung in nachfolgenden Mausereignissen verwendet wird, um Statusänderungen zu diesem Zeitpunkt zu verhindern. Die Variable wird im Klickereignis zurückgesetzt. Siehe Walter Romans Antwort auf dieser Seite. Dies ist eine anständige Lösung, wenn Sie wirklich keinen Hover-Effekt auf Touch-Interfaces wünschen. Leider funktioniert dies nicht, wenn a aus einem touchendanderen Grund ausgelöst wird und kein Klickereignis ausgelöst wird (z. B. wenn der Benutzer gescrollt oder gezoomt hat) und anschließend versucht, dem Link mit einer Maus zu folgen (dh auf einem Gerät mit Maus- und Touch-Oberfläche) ).

Weiterführende Literatur


1
Gute Antwort. Ich habe deine Geige benutzt, um meine eigene Lösung zu entwickeln. Das Touchend wird jedoch manchmal benötigt. (Wenn ein Touchmove nicht ausgeführt wird - dh wenn der Benutzer das Dokument selbst
verlässt

Große Antwort , aber in den meisten Fällen würde ich mit vorschlagen touchend anstelle von touchstartin den meisten Fällen sofort zu vermeiden Auslösung von Aktionen , wenn der Benutzer versucht , Swipe-Bildlauf nach oben oder unten vorzunehmen. Wird immer noch passieren, ist aber weniger ablenkend oder verwirrend (vorausgesetzt, es ist etwas harmloses wie das Anzeigen eines Etiketts, nicht etwas, von dem der Benutzer wissen muss, dass es passiert ist)
user56reinstatemonica8

19

Wie kann ich die Hover-Effekte erzielen, wenn ich die Maus verwende, sie jedoch unterdrücken, wenn ich den Touchscreen verwende?

Vielleicht denken Sie nicht so sehr daran, Hover-Effekte für Touchscreens zu unterdrücken, sondern Hover-Effekte für Mausereignisse hinzuzufügen?

Wenn Sie die :hoverEffekte in Ihrem CSS beibehalten möchten, können Sie verschiedene Stile für verschiedene Medien angeben:

@media screen { /* hover styles here */ } 

@media handheld { /* non-hover styles here */ }

Abgesehen davon, dass es leider viele mobile Geräte gibt, die dies ignorieren und nur die Bildschirmregeln verwenden. Glücklicherweise unterstützen viele neuere Browser für Mobilgeräte / Tablets einige ausgefallenere Medienabfragen:

@media screen and (max-width:800px) { /* non-hover styles here */ }

Selbst wenn der Teil "Bildschirm" oder "Handheld" ignoriert wird, erledigt die "maximale Breite" den Trick für Sie. Sie können einfach davon ausgehen, dass alles, was einen Bildschirm mit weniger als 800 Pixel hat, ein Tablet oder ein Telefon sein muss und keine Hover-Effekte verwendet. Für die seltenen Benutzer, die eine Maus auf einem Gerät mit niedriger Auflösung verwenden, würden sie die Hover-Effekte nicht sehen, aber Ihre Website wäre sonst in Ordnung.

Weitere Informationen zu Medienanfragen? Es gibt viele Artikel darüber online - hier ist einer: http://www.alistapart.com/articles/return-of-the-mobile-stylesheet

Wenn Sie die Hover-Effekte aus Ihrem CSS heraus verschieben und sie mit JavaScript anwenden, können Sie sie spezifisch an Mausereignisse binden und / oder Sie können einfach einige Annahmen treffen, die nur auf der Bildschirmgröße basieren, wobei das schlimmste "Problem" das einige ist Benutzer, die eine Maus verwenden, verpassen die Hover-Effekte.


Ich würde gerne Hover-Effekte nur für Mausereignisse hinzufügen. Berührungsereignisse emulieren jedoch Mausereignisse. Wenn ich die Berührungsereignisse einbinde und anrufe preventDefault(), werden die Mausereignisse manchmal unterdrückt, aber wie ich in meiner Frage sagte, ist dies nicht zuverlässig.
Joe White

6
Was passiert bei Medienabfragen, wenn Windows 8 herauskommt und PCs sowohl Touchscreens als auch Mäuse haben? Wenn der Benutzer mit der Maus schwebt, wird der Mauszeiger angezeigt, und ich möchte die Hover-Effekte. Wenn sie mit dem Touchscreen tippen, möchte ich die Hover-Effekte nicht. Aber ich habe keinen zuverlässigen Weg gefunden, um den Unterschied zwischen Berührung und Maus zu erkennen.
Joe White

Nun, vielleicht sind die Browser-Entwickler motivierter, die Erkennung konsistenter zu gestalten, sobald sie eine größere Anzahl von Benutzern auf Geräten mit Touch und Maus haben. Aber für den Moment? Ich würde basierend auf der Bildschirmgröße Vermutungen anstellen, aber die anderen Antworten enthalten andere Ratschläge. Entschuldigung, ich kann nicht weiter helfen.
nnnnnn

9

Ich habe das folgende JS für ein kürzlich erstelltes Projekt geschrieben, bei dem es sich um eine Desktop- / Mobil- / Tablet-Site handelt, die Hover-Effekte aufweist, die bei Berührung nicht angezeigt werden sollten.

Das folgende mobileNoHoverStateModul verfügt über eine Variable preventMouseover(ursprünglich deklariert als false), die festgelegt wird, truewenn ein Benutzer das touchstartEreignis für ein Element auslöst $target.

preventMouseoverwird dann zurückgesetzt, falsewenn das mouseoverEreignis ausgelöst wird, wodurch die Site wie beabsichtigt funktioniert, wenn ein Benutzer sowohl seinen Touchscreen als auch seine Maus verwendet.

Wir wissen, dass mouseoverdies nach touchstartder Reihenfolge ausgelöst wird, in der sie deklariert werden init.

var mobileNoHoverState = function() {

    var hoverClass = 'hover',
        $target = $(".foo"), 
        preventMouseover = false;

    function forTouchstart() {
        preventMouseover = true;
    }

    function forMouseover() {
        if (preventMouseover === false) {
            $(this).addClass(hoverClass);
        } else {
            preventMouseover = false;
        }
    }

    function forMouseout() {
        $(this).removeClass(hoverClass);
    }

    function init() {
        $target.on({
            touchstart  : forTouchstart,
            mouseover   : forMouseover,
            mouseout    : forMouseout
        });                
    }

    return {
        init: init
    };
}();

Das Modul wird dann weiter unten instanziiert:

mobileNoHoverState.init();

"PreventMouseover wird dann bei jedem Auslösen des Mouseover-Ereignisses auf" true "zurückgesetzt. Dadurch kann die Site wie beabsichtigt funktionieren, wenn ein Benutzer sowohl seinen Touchscreen als auch seine Maus verwendet." - Ihr Code macht das nicht. Vermisse ich etwas
Redtopia

@ Redtopia Danke für das Heads Up! Ich habe die Antwort mit dem Code aktualisiert, der weggelassen wurde.
Walter Roman

Sie brauchen keine Semikolons nach der Funktionsdeklaration
nacholibre

@nacholibre Die richtige Verwendung des Semikolons wurde eingerichtet
Walter Roman

6

Ich wollte wirklich selbst eine reine cssLösung dafür, da es eine unangenehme Option schien, eine gewichtige Javascript-Lösung um alle meine Ansichten zu streuen. Schließlich wurde die Abfrage @ media.hover gefunden , die erkennen kann, "ob der primäre Eingabemechanismus es dem Benutzer ermöglicht, über Elemente zu schweben". Dies vermeidet Berührungsgeräte, bei denen "Schweben" eher eine emulierte Aktion als eine direkte Fähigkeit des Eingabegeräts ist.

Also zum Beispiel, wenn ich einen Link habe:

<a href="/" class="link">Home</a>

Dann kann ich es nur :hoverdann sicher stylen, wenn das Gerät es damit problemlos unterstützt css:

@media (hover: hover) {
  .link:hover { /* hover styles */ }
}

Während die meisten modernen Browser Abfragen von Interaktionsmedienfunktionen unterstützen, tun dies einige gängige Browser wie IE und Firefox nicht. In meinem Fall funktioniert dies einwandfrei, da ich nur Chrome auf dem Desktop und Chrome und Safari auf Mobilgeräten unterstützen wollte.


Gute Lösung, die zu funktionieren scheint, wenn Sie Geräte in Chrome devtools emulieren. Aber es funktioniert immer noch nicht für Chrome Android :-(
Sjeiti

Ich denke, dies ist die bequemste und korrekteste Lösung. Ich hoffe, es wird bald zu den W3C-Standards hinzugefügt.
GProst

5

Meine Lösung besteht darin, dem HTML-Tag eine hover-aktive CSS-Klasse hinzuzufügen und sie am Anfang aller CSS-Selektoren zu verwenden mit: Hover und entfernen Sie diese Klasse beim ersten Touchstart-Ereignis.

http://codepen.io/Bnaya/pen/EoJlb

JS:

(function () {
    'use strict';

    if (!('addEventListener' in window)) {
        return;
    }

    var htmlElement = document.querySelector('html');

    function touchStart () {
        document.querySelector('html').classList.remove('hover-active');

        htmlElement.removeEventListener('touchstart', touchStart);
    }

    htmlElement.addEventListener('touchstart', touchStart);
}());

HTML:

<html class="hover-active">

CSS:

.hover-active .mybutton:hover {
    box-shadow: 1px 1px 1px #000;
}

Anstatt ein Touch-Ereignis anzuhören, können Sie es testen 'ontouchstart' in window. zBif ('ontouchstart' in window) document.querySelector('html').classList.remove('hover-active');
Yuval A.

@ YuvalA. Der Grund, warum ich auf das Touch-Ereignis warte, ist, dass es Geräte mit Zeiger- und Touch-Unterstützung gibt und der Benutzer den Zeiger verwendet, den ich nicht entfernen möchte. Es ist möglich, dass der Benutzer Touch und dann Zeiger verwendet, aber ich habe nicht viel zu tun
Bnaya

2

Was ich getan habe, um das gleiche Problem zu lösen, ist eine Feature-Erkennung (ich verwende so etwas wie diesen Code ), um zu sehen, ob onTouchMove definiert ist, und wenn ja, füge ich die CSS-Klasse "touchMode" zum Body hinzu, sonst füge ich hinzu " desktopMode ".

Jedes Mal, wenn ein Stileffekt nur für ein Touch-Gerät oder nur für einen Desktop gilt, wird der CSS-Regel die entsprechende Klasse vorangestellt:

.desktopMode .someClass:hover{ color: red }
.touchMode .mainDiv { width: 100%; margin: 0; /*etc.*/ }

Bearbeiten : Diese Strategie fügt Ihrem CSS natürlich ein paar zusätzliche Zeichen hinzu. Wenn Sie also Bedenken hinsichtlich der CSS-Größe haben, können Sie nach den TouchMode- und DesktopMode-Definitionen suchen und diese in verschiedene Dateien einfügen, damit Sie für jedes Gerät ein optimiertes CSS bereitstellen können Art; oder Sie könnten die Klassennamen in etwas viel kürzeres ändern, bevor Sie mit dem Stoßen beginnen.


2

Richtig, ich hatte ein ähnliches Problem, konnte es aber mit Medienabfragen und einfachem CSS beheben. Ich bin sicher, dass ich hier gegen einige Regeln verstoße, aber es funktioniert für mich.

Ich musste im Grunde genommen eine massive Bewerbung nehmen, die jemand gemacht hatte, und sie reaktionsfähig machen. Sie verwendeten jQueryUI und baten mich, keine ihrer jQuery zu manipulieren, sodass ich nur CSS verwenden durfte.

Wenn ich im Touchscreen-Modus eine ihrer Tasten drückte, wurde der Schwebeeffekt für eine Sekunde ausgelöst, bevor die Aktion der Taste wirksam wurde. Hier ist, wie ich es behoben habe.

@media only screen and (max-width:1024px) {

       #buttonOne{
            height: 44px;
        }


        #buttonOne:hover{
            display:none;
        }
}   

2

In meinem Projekt haben wir dieses Problem mithilfe von https://www.npmjs.com/package/postcss-hover-prefix und https://modernizr.com/ gelöst. Zuerst verarbeiten wir CSS-Ausgabedateien mit postcss-hover-prefix. Es fügt .no-touchfür alle CSS- hoverRegeln hinzu.

const fs = require("fs");
const postcss = require("postcss");
const hoverPrfx = require("postcss-hover-prefix");

var css = fs.readFileSync(cssFileName, "utf8").toString();
postcss()
   .use(hoverPrfx("no-touch"))
   .process(css)
   .then((result) => {
      fs.writeFileSync(cssFileName, result);
   });

CSS

a.text-primary:hover {
  color: #62686d;
}

wird

.no-touch a.text-primary:hover {
  color: #62686d;
}

Zur Laufzeit werden Modernizrautomatisch CSS-Klassen zu solchen htmlTags hinzugefügt

<html class="wpfe-full-height js flexbox flexboxlegacy canvas canvastext webgl 
  no-touch 
  geolocation postmessage websqldatabase indexeddb hashchange
  history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage
  borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients
  cssreflections csstransforms csstransforms3d csstransitions fontface
  generatedcontent video audio localstorage sessionstorage webworkers
  applicationcache svg inlinesvg smil svgclippaths websocketsbinary">

Eine solche Nachbearbeitung von CSS plus Modernizr deaktiviert das Hover für Touch-Geräte und ermöglicht es anderen. Tatsächlich wurde dieser Ansatz von Bootstrap 4 inspiriert, wie sie das gleiche Problem lösen: https://v4-alpha.getbootstrap.com/getting-started/browsers-devices/#sticky-hoverfocus-on-mobile


1

Sie können das mouseLeaveEreignis auslösen , wenn Sie ein Element auf dem Touchscreen berühren. Hier ist eine Lösung für alle <a>Tags:

function removeHover() {
    var anchors = document.getElementsByTagName('a');
    for(i=0; i<anchors.length; i++) {
        anchors[i].addEventListener('touchstart', function(e){
            $('a').mouseleave();
        }, false);
    }
}

JSHint sagt "mache keine Funktionen innerhalb einer Schleife".
NetOperator Wibby

Es ist ein Hack. Es ist KEIN wiederverwendbarer Code, der als bewährte Methode angesehen werden kann. @ NetOperatorWibby
sagte Kholov

Nun, es ist nicht wirklich hilfreich, Code zu posten, der nicht als gute Praxis angesehen werden kann. Das ist, als würde man ein Pflaster auf eine Messerwunde legen.
NetOperator Wibby

1

Ich hatte zwei Lösungen für das Problem gefunden, die implizierten, dass Sie Berührungen mit modernizr oder etwas anderem erkennen und eine Berührungsklasse für das HTML-Element festlegen.

Das ist gut , aber nicht unterstützt sehr gut:

html.touch *:hover {
    all:unset!important;
}

Dies hat aber eine sehr gute Unterstützung :

html.touch *:hover {
    pointer-events: none !important;
}

Funktioniert für mich einwandfrei. Dadurch werden alle Hover-Effekte so, als ob Sie eine Taste berühren. Sie leuchten auf, werden jedoch nicht als anfänglicher Hover-Effekt für Mausereignisse fehlerhaft.

Erkennen von Berührungen von berührungslosen Geräten Ich denke, modernizr hat die beste Arbeit geleistet:

https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js

BEARBEITEN

Ich habe eine bessere und einfachere Lösung für dieses Problem gefunden

So stellen Sie fest, ob der Client ein Touch-Gerät ist


0

Es könnte hilfreich sein, Ihr CSS zu sehen, da es sich nach einem ziemlich seltsamen Problem anhört. Aber wenn es passiert und alles andere gut ist, können Sie versuchen, den Hover-Effekt auf Javascript zu verschieben (Sie können auch jquery verwenden). Binden Sie einfach an das Mouseover- oder besser noch an das Mouseenter-Ereignis und beleuchten Sie Ihr Element, wenn das Ereignis ausgelöst wird.

Schauen Sie sich das letzte Beispiel hier an: http://api.jquery.com/mouseover/ . Sie können etwas Ähnliches verwenden, um zu protokollieren, wann das Ereignis ausgelöst wird, und es von dort zu übernehmen!


Nichts Besonderes am CSS; siehe meine Bearbeitung. Und ich habe es schon versucht mouseenter; kein Würfel. Durch Tippen wird der "unsichtbare Mauszeiger" bewegt, sodass er ausgelöst wird mouseenterund mousemove(und mouseleavewenn Sie auf eine andere Stelle tippen).
Joe White

0

Wenn Sie gerne JavaScript verwenden, können Sie Modernizr auf Ihrer Seite verwenden. Wenn die Seite geladen wird, wird in einem Nicht-Touchscreen-Browser die Klasse ".no-touch" zum HTML-Tag hinzugefügt. Bei einem Touchscreen-Browser wird dem HTML-Tag die Klasse ".touch" zum HTML-Tag hinzugefügt .

Dann müssen Sie lediglich überprüfen, ob das HTML-Tag die No-Touch-Klasse hat, bevor Sie sich entscheiden, Ihre Mouseenter- und Mouseleave-Listener hinzuzufügen.

if($('html').hasClass('no-touch')){
    $('.box').on("mouseenter", function(event){
            $(this).css('background-color','#0000ff')
    });
    $('.box').on("mouseleave", function(event){
            $(this).css('background-color','')
    });
}

Bei einem Touchscreen-Gerät haben die Ereignisse keine Listener, sodass Sie beim Tippen keinen Hover-Effekt erhalten.


Wenn es mit CSS gemacht werden kann, verwenden Sie kein Javascript (jquery), es ist eine Verschwendung von Computerleistung
Simon Dragsbæk

1
Noch einfacher ist es, wenn Sie in Ihrem CSS separate Regeln für .touchund definieren .no-touch. Ihre Antwort in CSS zusammen mit Modernizer neu zu schreiben html.no-touch .box:hover {background-color: "#0000ff"}und nichts dafür zu definieren, html.touch .box:hoversollte den Trick tun, da das OP nur versucht, mobile :hovers zu vermeiden .
Walter Roman

0

In einem Projekt, das ich kürzlich durchgeführt habe, habe ich dieses Problem mit der Funktion für delegierte Ereignisse von jQuery gelöst. Es sucht mithilfe eines jQuery-Selektors nach bestimmten Elementen und fügt diesen Elementen eine CSS-Klasse hinzu / entfernt sie, wenn sich die Maus über dem Element befindet. Soweit ich es testen konnte, scheint es gut zu funktionieren, einschließlich IE10 auf einem Touch-fähigen Notebook unter Windows 8.

$(document).ready(
    function()
    {
        // insert your own selector here: maybe '.hoverable'?
        var selector = 'button, .hotspot';

        $('body')
            .on('mouseover', selector, function(){ $(this).addClass('mouseover');    })
            .on('mouseout',  selector, function(){ $(this).removeClass('mouseover'); })
            .on('click',     selector, function(){ $(this).removeClass('mouseover'); });
    }
);

Bearbeiten: Für diese Lösung ist es natürlich erforderlich, dass Sie Ihr CSS ändern, um die Selektoren ": hover" zu entfernen, und im Voraus überlegen, welche Elemente Sie "schweben" möchten.

Wenn Sie sehr viele Elemente auf Ihrer Seite haben (wie mehrere Tausend), kann es jedoch etwas langsam werden, da diese Lösung Ereignisse von drei Typen auf allen Elementen auf der Seite abfängt und dann ihre Aufgabe erfüllt, wenn die Auswahl übereinstimmt. Ich habe die CSS-Klasse "mouseover" anstelle von "hover" genannt, weil ich nicht wollte, dass CSS-Leser ": hover" lesen, wo ich ".hover" geschrieben habe.


0

Hier ist meine Lösung: http://jsfiddle.net/agamemnus/g56aw709/-- Code unten.

Alles was man tun muss, ist das ": hover" in ".hover" umzuwandeln ... das war's! Der große Unterschied zwischen diesem und dem Rest besteht darin, dass dies auch bei nicht singulären Elementselektoren wie z .my_class > *:hover {.

handle_css_hover_effects ()

function handle_css_hover_effects (init) {
 var init = init || {}
 var handle_touch_events = init.handle_touch_events || true
 var handle_mouse_events = init.handle_mouse_events || true
 var hover_class         = init.hover_class         || "hover"
 var delay_preferences   = init.delay_preferences   || {touch: {add: 500, remove: 500}}
 function default_handler (curobj, input_type, op) {
  var hovered_element_selector = "*" + ((op == "add") ? ":" : ("." + hover_class))
  var hovered_elements = Array.prototype.slice.call(document.body.querySelectorAll(hovered_element_selector))
  var modified_list = []
  while (true) {
   if ((curobj == null) || (curobj == document.documentElement)) break
   if (hovered_elements.indexOf(curobj) != -1) modified_list.push (curobj)
   curobj = curobj.parentNode
  }
  function do_hover_change () {modified_list.forEach (function (curobj) {curobj.classList[op](hover_class)})}
  if ((!delay_preferences[input_type]) || (!delay_preferences[input_type][op])) {
   do_hover_change ()
  } else {
   setTimeout (do_hover_change, delay_preferences[input_type][op])
  }
 }

 if (handle_mouse_events) {
  document.body.addEventListener ('mouseover' , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "add")})
  document.body.addEventListener ('mouseout'  , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "remove")})
  document.body.addEventListener ('click'     , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "remove")})
 }

 if (handle_touch_events) {
  document.body.addEventListener ('touchstart', function (evt) {var curobj = evt.target; default_handler (curobj, "touch", "add")})
  document.body.addEventListener ('touchend'  , function (evt) {var curobj = evt.target; default_handler (curobj, "touch", "remove")})
  document.body.addEventListener ('touchmove',  function (evt) {
   var curobj = evt.target
   var hovered_elements = Array.prototype.slice.call(document.body.querySelectorAll("*:hover"))
   var lastobj = null
   evt = evt.changedTouches[0]
   var elements_at_point = get_elements_at_point (evt.pageX, evt.pageY)
   // Get the last element that isn't at the current point but is still hovered over, and remove only its hover attribute.
   while (true) {
    if ((curobj == null) || (curobj == document.documentElement)) break
    if ((hovered_elements.indexOf(curobj) != -1) && (elements_at_point.indexOf(curobj) == -1)) lastobj = curobj
    curobj = curobj.parentNode
   }
   if (lastobj == null) return
   if ((!delay_preferences.touch) || (!delay_preferences.touch.remove)) {
    lastobj.classList.remove(hover_class)
   } else {
    setTimeout (function () {lastobj.classList.remove(hover_class)}, delay_preferences.touch.remove)
   }

   function get_elements_at_point (x, y) {
    var el_list = [], pe_list = []
    while (true) {
     var curobj = document.elementFromPoint(x, y)
     if ((curobj == null) || (curobj == document.documentElement)) break
     el_list.push (curobj); pe_list.push (curobj.style.pointerEvents)
     curobj.style.pointerEvents = "none"
    }
    el_list.forEach (function (current_element, i) {current_element.style.pointerEvents = pe_list[i]})
    return el_list
   }
  })
 }
}

0

Fügen Sie Modernizr in Ihre Seite ein und legen Sie stattdessen Ihre Schwebezustände wie folgt fest:

html.no-touchevents .box:hover {
    background: blue;
}

0

Hallo Person aus der Zukunft, Sie möchten wahrscheinlich die pointerund / oder hoverMedienabfrage verwenden. Die handheldMedienabfrage war veraltet.

/* device is using a mouse or similar */
@media (pointer: fine) {
  a:hover {
    background: red;
  }
}

-1

Probieren Sie diese einfache jquery-Lösung für 2019 aus, obwohl es schon eine Weile her ist.

  1. füge dieses Plugin zu head hinzu:

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

  2. füge dies zu js hinzu:

    $("*").on("touchend", function(e) { $(this).focus(); }); //applies to all elements

  3. Einige vorgeschlagene Variationen davon sind:

    $(":input, :checkbox,").on("touchend", function(e) {(this).focus);}); //specify elements
    
    $("*").on("click, touchend", function(e) { $(this).focus(); });  //include click event`
    
    css: body { cursor: pointer; } //touch anywhere to end a focus`

Anmerkungen

  • Platzieren Sie das Plugin gegebenenfalls vor bootstrap.js, um eine Beeinträchtigung der QuickInfos zu vermeiden
  • Nur auf dem iPhone XR ios 12.1.12 und dem ipad 3 ios 9.3.5 mit Safari oder Chrome getestet.

Verweise:

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

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.