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 :hover
Effekten (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
, touchmove
und touchend
Ereignisse 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 preventDefault
nicht 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
, mousemove
und mouseleave
.
quelle
Antworten:
Ich gehe von Ihrer Frage aus, dass Ihr Hover-Effekt den Inhalt Ihrer Seite verändert. In diesem Fall rate ich:
touchstart
und hinzumouseenter
.mouseleave
,touchmove
undclick
.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):
touchstart
touchmove
touchend
mouseover
mouseenter
mouseover
,mouseenter
odermousemove
Ereignis den Seiteninhalt ändert, werden die folgenden Ereignisse nie gebrannt.mousemove
mousedown
mouseup
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:
touchstart
und hinzumouseenter
.mouseleave
,touchmove
undclick
.Beachten Sie, dass keine Aktion aktiviert ist
touchend
!Dies funktioniert eindeutig für Mausereignisse:
mouseenter
undmouseleave
(leicht verbesserte Versionen vonmouseover
undmouseout
) werden ausgelöst und fügen den Hover hinzu und entfernen ihn.Wenn der Benutzer tatsächlich einen
click
Link 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 dasclick
Ereignis 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
touchstart
Ereignis hat undclick
die 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
mouseleave
Ereignis ausgelöst wird und der Hover-Effekt bestehen bleibt. Zum Glück kann dies leicht behoben werden, indem der Hover-Effekt auf entfernt wirdtouchmove
.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:
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.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 einemtouchend
anderen 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
mouseover
oder einesmousemove
Ereignisses keine weiteren Ereignisse ausgelöst werden .quelle
touchend
anstelle vontouchstart
in 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)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
:hover
Effekte in Ihrem CSS beibehalten möchten, können Sie verschiedene Stile für verschiedene Medien angeben: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:
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.
quelle
preventDefault()
, werden die Mausereignisse manchmal unterdrückt, aber wie ich in meiner Frage sagte, ist dies nicht zuverlässig.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
mobileNoHoverState
Modul verfügt über eine VariablepreventMouseover
(ursprünglich deklariert alsfalse
), die festgelegt wird,true
wenn ein Benutzer dastouchstart
Ereignis für ein Element auslöst$target
.preventMouseover
wird dann zurückgesetzt,false
wenn dasmouseover
Ereignis ausgelöst wird, wodurch die Site wie beabsichtigt funktioniert, wenn ein Benutzer sowohl seinen Touchscreen als auch seine Maus verwendet.Wir wissen, dass
mouseover
dies nachtouchstart
der Reihenfolge ausgelöst wird, in der sie deklariert werdeninit
.Das Modul wird dann weiter unten instanziiert:
quelle
Ich wollte wirklich selbst eine reine
css
Lö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:
Dann kann ich es nur
:hover
dann sicher stylen, wenn das Gerät es damit problemlos unterstütztcss
: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.
quelle
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:
HTML:
CSS:
quelle
'ontouchstart' in window
. zBif ('ontouchstart' in window) document.querySelector('html').classList.remove('hover-active');
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:
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.
quelle
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.
quelle
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-touch
für alle CSS-hover
Regeln hinzu.CSS
wird
Zur Laufzeit werden
Modernizr
automatisch CSS-Klassen zu solchenhtml
Tags hinzugefügtEine 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
quelle
Sie können das
mouseLeave
Ereignis auslösen , wenn Sie ein Element auf dem Touchscreen berühren. Hier ist eine Lösung für alle<a>
Tags:quelle
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:
Dies hat aber eine sehr gute Unterstützung :
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.jsBEARBEITEN
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
quelle
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!
quelle
mouseenter
; kein Würfel. Durch Tippen wird der "unsichtbare Mauszeiger" bewegt, sodass er ausgelöst wirdmouseenter
undmousemove
(undmouseleave
wenn Sie auf eine andere Stelle tippen).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.
Bei einem Touchscreen-Gerät haben die Ereignisse keine Listener, sodass Sie beim Tippen keinen Hover-Effekt erhalten.
quelle
.touch
und definieren.no-touch
. Ihre Antwort in CSS zusammen mit Modernizer neu zu schreibenhtml.no-touch .box:hover {background-color: "#0000ff"}
und nichts dafür zu definieren,html.touch .box:hover
sollte den Trick tun, da das OP nur versucht, mobile:hover
s zu vermeiden .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.
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.
quelle
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 {
.quelle
Fügen Sie Modernizr in Ihre Seite ein und legen Sie stattdessen Ihre Schwebezustände wie folgt fest:
quelle
Hallo Person aus der Zukunft, Sie möchten wahrscheinlich die
pointer
und / oderhover
Medienabfrage verwenden. Diehandheld
Medienabfrage war veraltet.quelle
Probieren Sie diese einfache jquery-Lösung für 2019 aus, obwohl es schon eine Weile her ist.
füge dieses Plugin zu head hinzu:
src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"
füge dies zu js hinzu:
$("*").on("touchend", function(e) { $(this).focus(); }); //applies to all elements
Einige vorgeschlagene Variationen davon sind:
Anmerkungen
Verweise:
https://code.jquery.com/ui/
https://api.jquery.com/category/selectors/jquery-selector-extensions/
quelle