So verhindern Sie Sticky-Hover-Effekte für Tasten auf Touch-Geräten


144

Ich habe ein Karussell mit einer vorherigen und einer nächsten Schaltfläche erstellt, die immer sichtbar sind. Diese Schaltflächen haben einen Schwebezustand und werden blau. Auf Touch-Geräten wie dem iPad bleibt der Schwebezustand bestehen, sodass die Taste nach dem Tippen blau bleibt. Das will ich nicht

  • Ich könnte für jede Schaltfläche eine no-hoverKlasse hinzufügen ontouchendund mein CSS so gestalten: button:not(.no-hover):hover { background-color: blue; }Aber das ist wahrscheinlich ziemlich schlecht für die Leistung und behandelt Geräte wie das Chromebook Pixel (das sowohl einen Touchscreen als auch eine Maus hat) nicht richtig.

  • Ich könnte dem eine touchKlasse hinzufügen documentElementund mein CSS so gestalten: html:not(.touch) button:hover { background-color: blue; }Aber das funktioniert auch nicht auf Geräten mit Touch und Maus.

Was ich bevorzugen würde, ist das Entfernen des Schwebezustands ontouchend. Aber das scheint nicht möglich zu sein. Durch das Fokussieren eines anderen Elements wird der Schwebezustand nicht entfernt. Das manuelle Tippen auf ein anderes Element funktioniert, aber ich kann das in JavaScript nicht auslösen.

Alle Lösungen, die ich gefunden habe, scheinen unvollkommen zu sein. Gibt es eine perfekte Lösung?

Antworten:


55

Sie können den Schwebezustand entfernen, indem Sie die Verknüpfung vorübergehend aus dem DOM entfernen. Siehe http://testbug.handcraft.com/ipad.html


Im CSS haben Sie:

:hover {background:red;}

In der JS haben Sie:

function fix()
{
    var el = this;
    var par = el.parentNode;
    var next = el.nextSibling;
    par.removeChild(el);
    setTimeout(function() {par.insertBefore(el, next);}, 0)
}

Und dann haben Sie in Ihrem HTML:

<a href="#" ontouchend="this.onclick=fix">test</a>

3
@Chris Guter Punkt, ich habe das Beispiel geändert, um den onclick-Handler im ontouchend-Ereignis festzulegen.
Sjoerd Visscher

4
Bitte fügen Sie Ihrer Antwort nur minimalen Demonstrationscode hinzu. Vielen Dank! stackoverflow.com/help/how-to-answer
2540625

1
@SjoerdVisscher Ich habe es eingefügt. StackOverflow möchte, dass der Code in der Antwort enthalten ist, da Links verschwinden können. (In diesem Fall musste nicht nur durchgeklickt, sondern auch die Quelle angezeigt und herausgefunden werden, welche Bits die fragliche Technik sind.)
Darren Cook,

2
@ KevinBorders Ja, bei einigen Geräten kann die Zeitverzögerung zwischen dem Entfernen und dem erneuten Einsetzen des Elements sehr deutlich sein. Leider habe ich auf meinem Android 4.4-Gerät festgestellt, dass dies ohne setTimeout nicht funktioniert hat.
Rodney

1
Die Idee ist interessant, aber ich fand sie etwas ruckelig und nicht auf allen Touch-Geräten weit verbreitet. Ich würde eine weniger invasive Lösung bevorzugen, die auf der Erkennung von Berührungsunterstützung und reinem CSS
Lorenzo Polidori

83

Sobald CSS Media Queries Level 4 implementiert ist, können Sie Folgendes tun:

@media (hover: hover) {
    button:hover {
        background-color: blue;
    }
}

Oder auf Englisch: "Wenn der Browser das richtige / wahre / echte / nicht emulierte Schweben unterstützt (z. B. ein mausähnliches primäres Eingabegerät), wenden Sie diesen Stil an, wenn Sie den Mauszeiger buttondarüber halten."

Da dieser Teil von Media Queries Level 4 bisher nur in Chrome auf dem neuesten Stand der Technik implementiert wurde, habe ich eine Polyfüllung geschrieben , um dies zu beheben . Mit ihm können Sie das oben genannte futuristische CSS in Folgendes umwandeln:

html.my-true-hover button:hover {
    background-color: blue;
}

(Eine Variation der .no-touchTechnik) Wenn Sie dann clientseitiges JavaScript aus derselben Polyfüllung verwenden, die die Unterstützung für das Schweben erkennt, können Sie das Vorhandensein der my-true-hoverKlasse entsprechend umschalten :

$(document).on('mq4hsChange', function (e) {
    $(document.documentElement).toggleClass('my-true-hover', e.trueHover);
});

Vielen Dank! Für meine Zwecke scheint dies in den meisten Browsern caniuse.com/#search=media%20queries unterstützt zu werden und funktioniert hervorragend, danke!
Ragamufin

3
Sie müssen stattdessen auf caniuse.com/#feat=css-media-interaction schauen und sehen, dass es in Firefox und IE11 :( nicht unterstützt wird. Sie benötigen also die
Polyfüllung

Es scheint, dass die Polyfüllung nicht mehr unterstützt wird (Repo ist archiviert) und es erfordert jQuery ...
amoebe

Dies wird jetzt in mobilen Browsern weitgehend unterstützt und funktioniert wie ein Zauber. Ich denke, es sollte die akzeptierte Antwort sein.
Trevor Burnham

Dies ist definitiv die am einfachsten zu implementierende und beste Antwort. Funktioniert in Firefox auf Android Mobile und PC. Ich bin mir bei Dual-Touch- und Mausgeräten nicht sicher.
HalfMens

28

Dies ist ein häufiges Problem ohne perfekte Lösung. Das Schwebeverhalten ist bei einer Maus nützlich und bei Berührung meist schädlich. Das Problem wird durch Geräte wie Chromebook Pixel und Surface verschärft, die Touch und Maus unterstützen (nicht weniger!).

Die sauberste Lösung, die ich gefunden habe, besteht darin, das Schwebeverhalten nur zu aktivieren, wenn das Gerät keine Berührungseingabe unterstützt.

var isTouch =  !!("ontouchstart" in window) || window.navigator.msMaxTouchPoints > 0;

if( !isTouch ){
    // add class which defines hover behavior
}

Zugegeben, Sie verlieren den Schwebeflug auf Geräten, die dies möglicherweise unterstützen. Manchmal wirkt sich der Hover jedoch stärker aus als der Link selbst, z. B. möchten Sie möglicherweise ein Menü anzeigen, wenn sich ein Element im Hover befindet. Mit diesem Ansatz können Sie das Vorhandensein von Berührungen testen und möglicherweise ein anderes Ereignis bedingt anhängen.

Ich habe dies auf dem iPhone, iPad, Chromebook Pixel, Surface und einer Vielzahl von Android-Geräten getestet. Ich kann nicht garantieren, dass es funktioniert, wenn dem Mix ein generischer USB-Touch-Eingang (z. B. ein Stift) hinzugefügt wird.


1
Genial, das hat bei mir funktioniert, im Gegensatz zum Community-Wiki / Darren Cook-Antwort.
Jannik

1
Gute Antwort. Dies ist eine ähnliche Lösung: stackoverflow.com/a/39787268/885464
Lorenzo Polidori

11

Mit Modernizr können Sie Ihre Hover gezielt auf berührungslose Geräte ausrichten:

(Hinweis: Dies läuft nicht auf dem Snippet-System von StackOverflow. Überprüfen Sie stattdessen die jsfiddle. )

/* this one is sticky */
#regular:hover, #regular:active {
  opacity: 0.5;
}

/* this one isn't */
html.no-touch #no-touch:hover, #no-touch:active {
  opacity: 0.5;
}

Beachten Sie, dass :activedies nicht zielgerichtet sein muss, .no-touchda es sowohl auf Mobilgeräten als auch auf Desktops wie erwartet funktioniert.


Dies ist IMO die beste Antwort, ABER das Beispiel ist falsch. Es zeigt den gleichen Schwebezustand für Touch- und Non-Touch-Geräte. Der Schwebezustand sollte nur angewendet werden, wenn er .no-touchauf dem htmlTag vorhanden ist. Andernfalls erhält diese Antwort meinen Gütesiegel.
Morrisbret

2
Das Problem ist, dass Sie sich jetzt, da mausfähige Geräte mit Touchscreens überall sind, nicht mehr wirklich auf diese Methode verlassen können. Allerdings kann ich nicht viel von einem anderen Weg sehen, dies zu tun ... das ist ein ziemliches Dilemma
dudewad

Ich nehme an, eine Möglichkeit wäre, sowohl Modernizr als auch eine Bibliothek wie mobile-detect.js zu verwenden, um sicherzustellen, dass es sich entweder um ein Telefon oder ein Tablet handelt.
Gavin

Sie sind der Retter, vielen Dank, dies hat perfekt für mobile Geräte funktioniert
Shivam

8
$("#elementwithhover").click(function() { 
  // code that makes element or parent slide or otherwise move out from under mouse. 

  $(this).clone(true).insertAfter($(this));
  $(this).remove();
});

Sie können diese Antwort mit einem on () anstelle eines click () verbessern. Durch Entfernen des Elements aus dem DOM und erneutes Anhängen habe ich meine Klickereignisse verloren. Wenn ich meine Funktion mit on umschrieb, an das Element band, dann entfernte und hinzugefügte funktionierte. Zum Beispiel: `$ ('body'). On ('click', '# elementwithhover', function () {// klonen, einfügen, entfernen}); Ich werde darüber abstimmen, wenn Sie diese Änderung vornehmen.
Will Lanni

Der Klon true behält das Klickereignis auf dem neuen Element bei, das den Platz des Elements mit dem festsitzenden Schwebeflug einnimmt. Das ursprüngliche Element wird nach dem Klonen aus dem Dom entfernt.
Verard Sloggett

Super Bruder, 10x
Kaloyan Stamatov

Stundenlanges Suchen nach einem Fix und dies lieferte schließlich einen. Tausend Dank!
Phil917

8

Es gibt vier Möglichkeiten, um mit dem Sticky Hover auf Mobilgeräten umzugehen : Hier finden Sie eine Möglichkeit can touch, dem Dokument basierend auf dem aktuellen Eingabetyp des Benutzers dynamisch eine Klasse hinzuzufügen oder zu entfernen . Es funktioniert auch mit Hybridgeräten, bei denen der Benutzer möglicherweise zwischen Touch und Maus / Trackpad wechselt:

<script>

;(function(){
    var isTouch = false //var to indicate current input type (is touch versus no touch) 
    var isTouchTimer 
    var curRootClass = '' //var indicating current document root class ("can-touch" or "")

    function addtouchclass(e){
        clearTimeout(isTouchTimer)
        isTouch = true
        if (curRootClass != 'can-touch'){ //add "can-touch' class if it's not already present
            curRootClass = 'can-touch'
            document.documentElement.classList.add(curRootClass)
        }
        isTouchTimer = setTimeout(function(){isTouch = false}, 500) //maintain "istouch" state for 500ms so removetouchclass doesn't get fired immediately following a touch event
    }

    function removetouchclass(e){
        if (!isTouch && curRootClass == 'can-touch'){ //remove 'can-touch' class if not triggered by a touch event and class is present
            isTouch = false
            curRootClass = ''
            document.documentElement.classList.remove('can-touch')
        }
    }

    document.addEventListener('touchstart', addtouchclass, false) //this event only gets called when input type is touch
    document.addEventListener('mouseover', removetouchclass, false) //this event gets called when input type is everything from touch to mouse/ trackpad
})();

</script>

Dies ist der beste Weg, den ich finde. Wenn Sie den Timer auf 1000 ms erhöhen, können Sie auch das lange Drücken abdecken, siehe hier . Tolles Zeug!
Lowtechsun

8

Sie können den Hover-Effekt für Geräte überschreiben, die Hover nicht unterstützen. Mögen:

.my-thing {
    color: #BADA55;
}

.my-thing:hover {
    color: hotpink;
}

@media (hover: none) {
    .my-thing {
        color: #BADA55;
    }
}

Getestet und verifiziert unter iOS 12

Hutspitze zu https://stackoverflow.com/a/50285058/178959, um darauf hinzuweisen.


Dies ist die modernere Lösung, für die keine Javascript- oder DOM-Manipulation erforderlich ist. Sie bietet vollständige Browserunterstützung (außer IE) und sollte die akzeptierte Antwort sein.
Funkju

3

Ich wollte meine eigene Lösung veröffentlichen, aber als ich überprüfte, ob jemand sie bereits veröffentlicht hatte, stellte ich fest, dass @Rodney es fast geschafft hätte. Er vermisste es jedoch als letzten entscheidenden Punkt, der es zumindest in meinem Fall unpassend machte. Ich meine, auch ich habe die gleiche .fakeHoverKlassenaddition / -entfernung über mouseenterund mouseleaveEreigniserkennung genommen, aber das allein wirkt per se fast genau wie "echt" :hover. Ich meine: Wenn Sie auf ein Element in Ihrer Tabelle tippen, wird nicht erkannt, dass Sie es "verlassen" haben - und somit den Status "Fakehover" beibehalten.

Was ich getan habe, war einfach zuzuhören. clickWenn ich also auf die Schaltfläche "tippe", feuere ich manuell a ab mouseleave.

Si das ist mein endgültiger Code:

.fakeHover {
    background-color: blue;
}


$(document).on('mouseenter', 'button.myButton',function(){
    $(this).addClass('fakeHover');
});

$(document).on('mouseleave', 'button.myButton',function(){
    $(this).removeClass('fakeHover');
});

$(document).on('button.myButton, 'click', function(){
    $(this).mouseleave();
});

Auf diese Weise behalten Sie Ihre gewohnte hoverFunktionalität bei, wenn Sie eine Maus verwenden, wenn Sie einfach auf Ihren Tasten "schweben". Nun, fast alles: Der einzige Nachteil ist, dass es nach dem Klicken auf die Schaltfläche mit der Maus nicht in seinem hoverZustand ist. Ähnlich wie wenn Sie geklickt und den Zeiger schnell aus der Schaltfläche genommen haben. Aber in meinem Fall kann ich damit leben.


2

Dies ist, was ich mir bisher ausgedacht habe, nachdem ich den Rest der Antworten studiert habe. Es sollte in der Lage sein, Nur-Touch-, Nur-Maus- oder Hybrid-Benutzer zu unterstützen.

Erstellen Sie eine separate Hover-Klasse für den Hover-Effekt. Fügen Sie diese Hover-Klasse standardmäßig unserer Schaltfläche hinzu.

Wir möchten das Vorhandensein von Touch-Unterstützung nicht erkennen und alle Hover-Effekte von Anfang an deaktivieren. Wie von anderen erwähnt, werden Hybridgeräte immer beliebter. Menschen haben möglicherweise Touch-Unterstützung, möchten aber eine Maus verwenden und umgekehrt. Entfernen Sie daher die Hover-Klasse nur, wenn der Benutzer die Schaltfläche tatsächlich berührt.

Das nächste Problem ist, was ist, wenn der Benutzer nach dem Berühren der Taste wieder eine Maus verwenden möchte? Um dies zu lösen, müssen wir einen geeigneten Moment finden, um die von uns entfernte Schwebeklasse wieder hinzuzufügen.

Wir können es jedoch nicht sofort nach dem Entfernen wieder hinzufügen, da der Schwebezustand noch aktiv ist. Möglicherweise möchten wir nicht auch den gesamten Button zerstören und neu erstellen.

Daher habe ich mir überlegt, einen Algorithmus zum Warten auf Besetzt (mit setInterval) zu verwenden, um den Schwebezustand zu überprüfen. Sobald der Schwebezustand deaktiviert ist, können wir die Schwebeklasse wieder hinzufügen und das Warten beenden, um zum ursprünglichen Zustand zurückzukehren, in dem der Benutzer entweder Maus oder Berührung verwenden kann.

Ich weiß, dass das Warten beschäftigt nicht so toll ist, aber ich bin mir nicht sicher, ob es ein geeignetes Ereignis gibt. Ich habe überlegt, es im Mouseleave-Event wieder hinzuzufügen, aber es war nicht sehr robust. Wenn beispielsweise nach dem Berühren der Taste eine Warnung angezeigt wird, verschiebt sich die Mausposition, aber das Mausblattereignis wird nicht ausgelöst.

var button = document.getElementById('myButton');

button.ontouchstart = function(e) {
  console.log('ontouchstart');
  $('.button').removeClass('button-hover');
  startIntervalToResetHover();
};

button.onclick = function(e) {
  console.log('onclick');
}

var intervalId;

function startIntervalToResetHover() {
  // Clear the previous one, if any.
  if (intervalId) {
    clearInterval(intervalId);
  }
  
  intervalId = setInterval(function() {
    // Stop if the hover class already exists.
    if ($('.button').hasClass('button-hover')) {
      clearInterval(intervalId);
      intervalId = null;
      return;
    }
    
    // Checking of hover state from 
    // http://stackoverflow.com/a/8981521/2669960.
    var isHovered = !!$('.button').filter(function() {
      return $(this).is(":hover");
    }).length;
    
    if (isHovered) {
      console.log('Hover state is active');
    } else {
      console.log('Hover state is inactive');
      $('.button').addClass('button-hover');
      console.log('Added back the button-hover class');
      
      clearInterval(intervalId);
      intervalId = null;
    }
  }, 1000);
}
.button {
  color: green;
  border: none;
}

.button-hover:hover {
  background: yellow;
  border: none;
}

.button:active {
  border: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='myButton' class='button button-hover'>Hello</button>

Bearbeiten: Ein anderer Ansatz, den ich versucht habe, ist das Aufrufen von e.preventDefault()ontouchstart oder ontouchend. Es scheint den Hover-Effekt zu stoppen, wenn die Schaltfläche berührt wird, aber es stoppt auch die Schaltfläche-Klick-Animation und verhindert, dass die Onclick-Funktion aufgerufen wird, wenn die Schaltfläche berührt wird. Sie müssen diese also manuell im ontouchstart- oder ontouchend-Handler aufrufen. Keine sehr saubere Lösung.


1

Es war hilfreich für mich: Link

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");
                    }
                }
            }
        }
    }
}

Sie müssen hoverTouchUnstick () einmal vom globalen ontouchstart-Ereignishandler aufrufen. Und diese Lösung würde perfekt funktionieren.
Jusid

1

Fügen Sie diesen JS-Code Ihrer Seite hinzu:

document.body.className = 'ontouchstart' in document.documentElement ? '' : 'hover';

Fügen Sie jetzt in Ihrem CSS vor jedem Hover die Hover-Klasse wie folgt hinzu:

.hover .foo:hover {}

Wenn das Gerät berührt wird, ist die Körperklasse leer, andernfalls schwebt die Klasse und die Regeln werden angewendet!


Hat bei mir nicht funktioniert, aber das hat funktioniert:document.body.className = 'ontouchstart' in window ? '' : 'hover';
drskullster

1

Ich könnte für jede Schaltfläche eine No-Hover-Klasse hinzufügen und mein CSS wie folgt gestalten: button: not (.no-hover): hover {Hintergrundfarbe: blau; } aber das ist wahrscheinlich ziemlich schlecht für die Leistung und behandelt> Geräte wie das Chromebook Pixel (das sowohl einen Touchscreen als auch eine Maus hat)> nicht richtig.

Dies ist der richtige Ausgangspunkt. Nächster Schritt: Anwenden / Entfernen der Nohover-Klasse auf folgende Ereignisse (Demo mit jQuery)

buttonelement
 .on("touchend touchcancel",function(){$(this).addClass("nohover")})
 .on("touchstart mouseover",function({$(this).removeClass("nohover")});   

Hinweis: Wenn Sie andere Klassen auf das Schaltflächenelement anwenden möchten, funktioniert das: not (.nohover) im CSS nicht mehr wie erwartet. Dann müssen Sie stattdessen eine separate Definition mit Standardwert und! Wichtigem Tag hinzufügen, um den Schwebestil zu überschreiben: .nohover {Hintergrundfarbe: weiß! Wichtig}

Dies sollte sogar Geräte wie das Chromebook Pixel (das sowohl einen Touchscreen als auch eine Maus hat) korrekt handhaben! Und ich denke nicht, dass dies ein großer Leistungskiller ist ...


1

Eine Lösung, die für mich funktioniert hat:

html {
   -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

Fügen Sie diesen Code Ihrem Stylesheet hinzu.

Ich wollte den grauen Hintergrund entfernen, der auf iOS Safari angezeigt wird, wenn auf einen Link geklickt wird. Aber es scheint mehr zu tun. Jetzt wird das Klicken auf eine Schaltfläche (mit einer :hoverPseudoklasse!) Sofort geöffnet! Ich habe es nur auf einem iPad getestet, ich weiß nicht, ob es auf anderen Geräten funktioniert.


1

Ich denke, ich habe eine elegante (Minimum js) Lösung für ein ähnliches Problem gefunden:

Mit jQuery können Sie mithilfe von jover einen Hover auf dem Körper (oder einem anderen Element) auslösen .mouseover()

Also füge ich dem ontouchendEreignis des Elements einfach einen solchen Handler hinzu :

var unhover = function() {
  $("body").mousover();  
};
.hoverable {
  width: 100px;
  height: 100px;
  background: teal;
  cursor: pointer;
}

.hoverable:hover {
  background: pink;
}
<div class="hoverable" ontouchend={unhover}></div>

Dies entfernt jedoch nur: Schweben Sie die Pseudoklasse aus dem Element, nachdem ein anderes Berührungsereignis ausgelöst wurde, z. B. Wischen oder eine andere Berührung


1
Für Ihr Code-Snippet bleibt das Quadrat immer noch rosa, nachdem ich es berührt habe. Ich denke, Sie haben das in dieser Frage gestellte Problem nicht wirklich gelöst?
Kevin Lee

Diese Lösung funktioniert nicht. Zuerst haben Sie die falsche Methode verwendet, um ein Ereignis aufzurufen. Sie sollten .trigger () verwenden . Zweitens funktioniert auf mobilen Safari so oder so nicht.
xHocquet

1

Ich habe eine schöne Lösung, die ich gerne teilen möchte. Zuerst müssen Sie feststellen, ob der Benutzer wie folgt mobil ist:

var touchDevice = /ipad|iphone|android|windows phone|blackberry/i.test(navigator.userAgent.toLowerCase());

Dann fügen Sie einfach hinzu:

if (!touchDevice) {
    $(".navbar-ul").addClass("hoverable");
}

Und in CSS:

.navbar-ul.hoverable li a:hover {
    color: #fff;
}

2
Funktioniert nicht auf Hybridgeräten, z. B. Windows-Touchscreen-PCs.
Cspolton

1

Ich ging durch das ähnliche Problem, meine Anwendung war für alle Bildschirmgrößen kompatibel und hatte eine Menge Hover-Effekte bei Geräten mit Desktop-Bildschirmgröße / Maus. Später stellte ich fest, dass berührungsbasierte Geräte einen als klebrig bezeichneten Zustand verursachten -Hover und es war eine Hürde für die App, für Benutzer von berührungsbasierten Geräten ordnungsgemäß zu funktionieren.

Wir haben SCSS in unserer App verwendet. und ich habe ein Mixin definiert , das sich um Touch-basierte Geräte kümmert.

@mixin hover-support {
  @media not all and (pointer: coarse) {
    &:hover {
      @content;
    }
  }
}

und dann habe ich alle meine CSS-Klassen unter das unten genannte Snippet gestellt.

   @include hover-support() {
    // Your css-classes or css that you want to apply on those devices that support hover.
   }

Zum Beispiel hatten wir eine Klasse zum Animieren eines Symbols, die ausgelöst wurde, sobald wir mit der Maus über das Symbol fahren, wie Sie es in CSS sehen können. Bei berührungsbasierten Geräten wurde es jedoch durch einen Sticky-Hover-Effekt beeinflusst, und dann habe ich es in @ platziert Fügen Sie hover-support () hinzu , um sicherzustellen, dass hover nur für Geräte gilt, die hover unterstützen.

@include hover-support() {
  .animate-icon {
    -webkit-transition: all 0.2s;
    transition: all 0.2s;
    &:hover {
      transform: scale(1.3);
      filter: brightness(85%);
      cursor: pointer;
    }
  }
}

1

Hier ist ein einfacher JavaScript-Code, bei dem der Entwickler kein CSS bearbeiten oder neue CSS-Regeln schreiben muss. Ich habe dies für Bootstrap-Schaltflächen mit geschrieben class="btn", aber es funktioniert mit jeder Schaltfläche, die einen bestimmten Klassennamen hat.

Die Schritte sind:

  1. Stellen Sie fest, ob es sich um ein Touch-Gerät handelt
  2. Wenn dies der Fall ist, durchlaufen Sie jede CSS-Regel in document.styleSheets
  3. Löschen Sie alle Regeln, die sowohl .btnals als auch enthalten:hover

Durch das Eliminieren aller .btn :hoverCSS-Regeln wird sichergestellt, dass auf einer Schaltfläche kein visueller Hover-Effekt auftritt.

Schritt 1: Touch-Gerät erkennen

Überprüfen Sie die Medienabfrage auf Folgendes (hover: none):

    const hasMatchMedia = typeof window.matchMedia !== 'undefined';
    /**
     * determine if device is touch-capable
     * true - device is touch-capable
     * false - device is not touch-capable
     * null - unable to determine touch capability
     * @return {null|boolean}
     */
    const hasTouch = () => {
      if (hasMatchMedia) {
        return window.matchMedia('(hover: none)').matches;
      }
      return null;
    };

Schritt 2: Löschen Sie CSS-Regeln, die "btn" und ": hover" enthalten

    /**
     * remove all CSS rules contaning both '.btn' and ':hover'
     * @return {number} count of rules deleted
     */
    function removeBtnHovers () {

      let rulesDeleted = 0;

      // recursively delete '.btn:hover' rules
      function recursiveDelete (rules, styleSheet) {

        if (typeof rules === 'undefined' ||
          typeof rules.length === 'undefined' ||
          rules.length <= 0) {
          return;
        }

        // iterate in reverse order,
        // deleting any rule containing both '.btn' and ':hover'
        const ruleLen = rules.length;
        for (let i = ruleLen - 1; i >= 0; i--) {
          const rule = rules[i];
          if (typeof rule.cssRules === 'undefined') {
            // a standard rule, evaluate it
            const cssText = rule.cssText;
            if (typeof cssText === 'string' &&
              cssText.includes('.btn') &&
              cssText.includes(':hover')) {
              styleSheet.deleteRule(i);
              rulesDeleted++;
            }
          } else {
            // rule contains cssRules, iterate over them
            recursiveDelete(rule.cssRules, rule);
          }
        }
      }

      // iterate over all style sheets in document
      for (const styleSheet of document.styleSheets) {
        let rules = styleSheet.cssRules;
        if (!rules) { continue; }
        recursiveDelete(rules, styleSheet);
      }
      return rulesDeleted;
    }

Der vollständige Code ist auf GitHub und npm .

Live-Demo auf terrymorse.com .


Entfernt dies nicht auch den Hover-Effekt für Touchscreen-Geräte mit Maus / Trackpad?
Jensei

@Jensei Möglicherweise. Hover-Regeln werden entfernt, wenn das Gerät übereinstimmt @media (hover:none)oder wenn der Benutzer den Bildschirm zum ersten Mal berührt. Sie können es auf der Live-Demo-Seite ausprobieren, um sicherzugehen.
Terrymorse

0

Sie können die Hintergrundfarbe :activefür :focus den Status festlegen und den standardmäßigen Hintergrund angeben.

Wenn Sie die Hintergrundfarbe über einstellen onfocus/ontouch, bleibt der Farbstil erhalten, sobald der :focusStatus abgelaufen ist.
Sie müssen ebenfalls zurücksetzen onblur, um defaut bg wiederherzustellen, wenn der Fokus verloren geht.


Aber ich möchte den Hover-Effekt für Mausbenutzer beibehalten.
Chris

: hover und: active können dasselbe CSS empfangen, es ist auf: focus Sie haben das Problem. Wenn Sie die Hintergrundfarbe über den Fokus einstellen, bleibt der Farbstil erhalten, sobald der Fokus weg ist. Sie benötigen auch einen Reset auf onlur, um defaut bg
G-Cyrillus

0

Das hat bei mir funktioniert: Setzen Sie das Hover-Styling in eine neue Klasse

.fakehover {background: red}

Fügen Sie dann die Klasse nach Bedarf hinzu oder entfernen Sie sie

$(".someclass > li").on("mouseenter", function(e) {
  $(this).addClass("fakehover");
});
$(".someclass > li").on("mouseleave", function(e) {
  $(this).removeClass("fakehover");
});

Wiederholen Sie diesen Vorgang für Touchstart- und Touchend-Ereignisse. Oder welche Ereignisse Sie möchten, um das gewünschte Ergebnis zu erzielen, zum Beispiel wollte ich, dass der Hover-Effekt auf einem Touchscreen umgeschaltet wird.


0

Basierend auf der Antwort von Darren Cooks, die auch funktioniert, wenn Sie Ihren Finger über ein anderes Element bewegen.

Siehe Finger suchen Element ist während eines Touchend-Ereignisses aktiviert

jQuery(function() {
    FastClick.attach(document.body);
});
// Prevent sticky hover effects for buttons on touch devices
// From https://stackoverflow.com/a/17234319
//
//
// Usage:
// <a href="..." touch-focus-fix>..</a>
//
// Refactored from a directive for better performance and compability
jQuery(document.documentElement).on('touchend', function(event) {
  'use strict';

  function fix(sourceElement) {
    var el = $(sourceElement).closest('[touch-focus-fix]')[0];
    if (!el) {
      return;
    }
    var par = el.parentNode;
    var next = el.nextSibling;
    par.removeChild(el);
    par.insertBefore(el, next);
  }

  fix(event.target);
  var changedTouch = event.originalEvent.changedTouches[0];
  // http://www.w3.org/TR/2011/WD-touch-events-20110505/#the-touchend-event
  if (!changedTouch) {
    return;
  }
  var touchTarget = document.elementFromPoint(changedTouch.clientX, changedTouch.clientY);
  if (touchTarget && touchTarget !== event.target) {
    fix(touchTarget);
  }
});

Codepen Demo


0

Sie können diesen Weg versuchen.

Javascript:

var isEventSupported = function (eventName, elementName) {
    var el = elementName ? document.createElement(elementName) : window;
    eventName = 'on' + eventName;
    var isSupported = (eventName in el);
    if (!isSupported && el.setAttribute) {
        el.setAttribute(eventName, 'return;');
        isSupported = typeof el[eventName] == 'function';
    }
    el = null;
    return isSupported;
};

if (!isEventSupported('touchstart')) {
    $('a').addClass('with-hover');
}

CSS:

a.with-hover:hover {
  color: #fafafa;
}

0

Was ich bisher in meinen Projekten getan habe, war, die :hoverÄnderungen auf Touch-Geräten rückgängig zu machen:

.myhoveredclass {
    background-color:green;
}
.myhoveredclass:hover {
    background-color:red;
}
@media screen and (-webkit-min-device-pixel-ratio:0) {
    .myhoveredclass:hover, .myhoveredclass:active, .myhoveredclass:focus {
        background-color:green;
    }
}

Alle Klassennamen und benannten Farben nur zu Demonstrationszwecken ;-)


0

Dies funktioniert perfekt in 2 Schritten.

  1. Stellen Sie Ihr Body-Tag so ein <body ontouchstart="">. Ich bin kein Fan dieses "Hacks", aber es ermöglicht Safari unter iOS, sofort auf Berührungen zu reagieren. Ich weiß nicht wie, aber es funktioniert.

  2. Richten Sie Ihre berührbare Klasse folgendermaßen ein:

    // I did this in SASS, but this should work with normal CSS as well
    
    // Touchable class
    .example {
    
        // Default styles
        background: green;
    
        // Default hover styles 
        // (Think of this as Desktop and larger)
        &:hover {
            background: yellow;
        }
    
        // Default active styles
        &:active {
            background: red;
        }
    
        // Setup breakpoint for smaller device widths
        @media only screen and (max-width: 1048px) {
    
            // Important!
            // Reset touchable hover styles
            // You may want to use the same exact styles as the Default styles
            &:hover {
                background: green;
            }
    
            // Important!
            // Touchable active styles
            &:active {
                background: red;
            }
        }
    }

Möglicherweise möchten Sie auch Animationen in Ihrer berührbaren Klasse entfernen. Android Chrome scheint etwas langsamer zu sein als iOS.

Dies führt auch dazu, dass der aktive Status angewendet wird, wenn der Benutzer die Seite scrollt, während er Ihre Klasse berührt.


0

Einige der klebrigen oder feststeckenden :hover :focus :activeProbleme auf Mobilgeräten können durch fehlende Probleme verursacht werden, <meta name="viewport" content="width=device-width">wenn die Browser versuchen, den Bildschirm zu manipulieren.


0

Die Lösung für mich war nach dem Touchend, den Knoten zu klonen und zu ersetzen ... Ich hasse es, dies zu tun, aber selbst der Versuch, das Element mit offsetHeight neu zu malen, funktionierte nicht

    let cloneNode = originNode.cloneNode( true );
    originNode.parentNode.replaceChild( cloneNode, originNode );

Am Ende hat das bei mir nicht funktioniert ... in meinem Fall müsste ich einen kompletten ES6 klonen, der erweitert ist, und mehrere Event-Listener, und es wurde einfach zu kompliziert, so eine winzige Sache zu lösen.
Verbot

0

Dies kann durch Austauschen einer HTML-Klasse erreicht werden. Es sollte weniger störanfällig sein als das Entfernen des gesamten Elements, insbesondere bei großen Bildverknüpfungen usw.

Wir können auch entscheiden, ob wir schweben wollen Zustände ausgelöst werden , wenn sie mit Berührung (Berührungsbewegungs ) oder sogar fügen Sie ein Timeout Scrollen sie zu verzögern.

Die einzige wesentliche Änderung in unserem Code ist die Verwendung zusätzlicher HTML-Klassen, z. B. <a class='hover'></a>für Elemente, die das neue Verhalten implementieren.

HTML

<a class='my-link hover' href='#'>
    Test
</a>

CSS

.my-link:active, // :active can be turned off to disable hover state on 'touchmove'
.my-link.hover:hover {

    border: 2px dotted grey;
}

JS (mit jQuery)

$('.hover').bind('touchstart', function () {

   var $el;
   $el = $(this);
   $el.removeClass('hover'); 

   $el.hover(null, function () {
      $el.addClass('hover');
   });
});

Beispiel

https://codepen.io/mattrcouk/pen/VweajZv

- -

Ich habe jedoch kein Gerät mit Maus und Touch, um es richtig zu testen.

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.