Come prevenire gli effetti di hover appiccicoso per i pulsanti sui dispositivi touch


144

Ho creato una giostra con un pulsante precedente e uno successivo che sono sempre visibili. Questi pulsanti hanno uno stato al passaggio del mouse, diventano blu. Sui dispositivi touch, come iPad, lo stato al passaggio del mouse è appiccicoso, quindi il pulsante rimane blu dopo averlo toccato. Non lo voglio.

  • Potrei aggiungere una no-hoverclasse ontouchendper ciascun pulsante e rendere così il mio CSS in questo modo: button:not(.no-hover):hover { background-color: blue; }ma probabilmente è piuttosto negativo per le prestazioni e non gestisce correttamente dispositivi come il Chromebook Pixel (che ha sia un touchscreen che un mouse).

  • Potrei aggiungere una touchclasse al documentElemente rendere il mio CSS in questo modo: html:not(.touch) button:hover { background-color: blue; }Ma anche quello non funziona proprio sui dispositivi con il tocco e il mouse.

Quello che preferirei è rimuovere lo stato al passaggio del mouse ontouchend. Ma non sembra che sia possibile. La messa a fuoco di un altro elemento non rimuove lo stato al passaggio del mouse. Toccando un altro elemento manualmente, non riesco a attivarlo in JavaScript.

Tutte le soluzioni che ho trovato sembrano imperfette. C'è una soluzione perfetta?

Risposte:


55

È possibile rimuovere lo stato al passaggio del mouse rimuovendo temporaneamente il collegamento dal DOM. Vedi http://testbug.handcraft.com/ipad.html


Nel CSS hai:

:hover {background:red;}

Nel JS hai:

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

E poi nel tuo HTML hai:

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

3
@Chris Un buon punto, ho cambiato l'esempio per impostare il gestore onclick nell'evento ontouchend.
Sjoerd Visscher,

4
Ti preghiamo di considerare di aggiungere un codice dimostrativo minimo alla tua risposta. Grazie! stackoverflow.com/help/how-to-answer
2540625

1
@SjoerdVisscher L'ho incollato. A StackOverflow piace che il codice sia nella risposta, poiché i collegamenti possono andare via. (E in questo caso non bastava semplicemente fare clic, ma poi visualizzare la fonte e capire quali bit sono la tecnica in questione.)
Darren Cook,

2
@KevinBorders sì su alcuni dispositivi il ritardo tra la rimozione e il reinserimento dell'elemento può essere molto evidente. Sfortunatamente, ho trovato sul mio dispositivo Android 4.4 che farlo senza setTimeout non ha funzionato.
Rodney,

1
L'idea è interessante, ma l'ho trovata un po 'a scatti e non ampiamente supportata su tutti i dispositivi touch. Preferirei una soluzione meno invasiva basata sul rilevamento del supporto touch e su CSS puri come questo stackoverflow.com/a/39787268/885464
Lorenzo Polidori

83

Dopo l' implementazione di Media Media Query CSS 4 , sarai in grado di farlo:

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

O in inglese: "Se il browser supporta l'hovering corretto / vero / reale / non emulato (ad es. Ha un dispositivo di input primario simile al mouse), applica questo stile quando buttonsi passa il mouse sopra".

Dato che questa parte di Media Query Level 4 è stata finora implementata solo in Chrome all'avanguardia, ho scritto un polyfill per gestirlo . Usandolo, puoi trasformare il CSS futuristico sopra in:

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

(Una variante della .no-touchtecnica) E quindi usando alcuni JavaScript lato client dallo stesso polyfill che rileva il supporto per il passaggio del mouse, puoi attivare / disattivare la presenza della my-true-hoverclasse di conseguenza:

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

Grazie! Per i miei scopi questo sembra essere supportato nella maggior parte dei browser caniuse.com/#search=media%20queries e funziona alla grande, grazie!
Ragamufin,

3
Devi invece guardare caniuse.com/#feat=css-media-interaction e vedrai che non è supportato in Firefox e IE11 :( quindi hai bisogno del polyfill
CherryDT

Sembra che il polyfill non sia più supportato (il repository è archiviato) e richiede jQuery ...
amoebe

Questo è ora ampiamente supportato nei browser mobili e funziona come un fascino. Penso che dovrebbe essere la risposta accettata.
Trevor Burnham,

Questa è sicuramente la più semplice da implementare e la migliore risposta. Funziona in Firefox su Android Mobile e PC. Non sono sicuro dei dispositivi dual touch e mouse.
HalfMens

28

Questo è un problema comune senza soluzione perfetta. Il comportamento al passaggio del mouse è utile con il mouse e per lo più dannoso con il tocco. Ad aggravare il problema ci sono dispositivi che supportano il tocco e il mouse (contemporaneamente, non meno!) Come il Chromebook Pixel e Surface.

La soluzione più pulita che ho trovato è abilitare il comportamento al passaggio del mouse solo se il dispositivo non supporta l'input touch.

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

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

Certo, si perde il passaggio del mouse sui dispositivi che potrebbero supportarlo. Tuttavia, a volte il passaggio del mouse ha un impatto maggiore rispetto al collegamento stesso, ad esempio forse si desidera mostrare un menu quando si passa il mouse su un elemento. Questo approccio consente di verificare l'esistenza del tocco e forse di associare condizionalmente un evento diverso.

Ho provato questo su iPhone, iPad, Chromebook Pixel, Surface e una varietà di dispositivi Android. Non posso garantire che funzionerà quando si aggiunge un input tattile USB generico (come uno stilo) al mix.


1
Fantastico, questo ha funzionato per me, a differenza della wiki della community / risposta di Darren Cook.
Jannik,

1
Buona risposta. Questa è una soluzione simile: stackoverflow.com/a/39787268/885464
Lorenzo Polidori

11

Con Modernizr puoi indirizzare i tuoi hovers in modo specifico per i dispositivi no-touch:

(Nota: questo non funziona sul sistema di snippet di StackOverflow, controlla invece 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;
}

Nota che :activenon ha bisogno di essere preso di mira .no-touchperché funziona come previsto su dispositivi mobili e desktop.


Questa è la risposta migliore IMO MA l'esempio non è corretto. Sta mostrando lo stesso stato al passaggio del mouse per i dispositivi touch e non touch. Dovrebbe applicare lo stato al passaggio del mouse solo se .no-touchè presente sul htmltag. Altrimenti, questa risposta ottiene il mio timbro di approvazione.
morrisbret,

2
Il problema è che ora che i dispositivi abilitati per il mouse con touchscreen sono ovunque, non puoi più fare affidamento su questo metodo. Tuttavia non riesco a vedere un altro modo per farlo ... questo è piuttosto un dilemma
dudewad

Suppongo che un modo per farlo sarebbe usare sia Modernizr sia una libreria come mobile-detect.js per assicurarsi che sia un telefono o un tablet.
Gavin,

Sei l'uomo salvatore grazie mille ha funzionato perfettamente per i dispositivi mobili
Shivam

9

Puoi ignorare l'effetto hover per i dispositivi che non supportano l'hover. Piace:

.my-thing {
    color: #BADA55;
}

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

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

Testato e verificato su iOS 12

Punta del cappello a https://stackoverflow.com/a/50285058/178959 per la precisazione.


Questa è la soluzione più moderna, non richiede manipolazione javascript o DOM, ha il supporto completo del browser (tranne IE) e dovrebbe essere la risposta accettata.
funkju,

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

Puoi migliorare questa risposta usando un on () anziché un click (). Rimuovendo l'elemento dal DOM e ricollegandolo, ho perso i miei eventi di clic. Quando riscrivo la mia funzione con on, rilegando l'elemento, quindi rimuovendo e aggiungendo funzionato. Ad esempio: `$ ('body'). On ('click', '# elementwithhover', function () {// clone, insertafter, remove}); Voterò questo se apporterai questa modifica.
Will Lanni,

il clone true conserva l'evento click sul nuovo elemenet prendendo il posto dell'elemento con il passaggio del mouse bloccato. l'elemento originale viene rimosso dal dom dopo la sua clonazione.
Verard Sloggett,

fantastico fratello, 10x
Kaloyan Stamatov,

Ore di ricerca di una correzione e questo finalmente fornito uno. Grazie mille!
phil917

8

Da 4 modi per gestire il passaggio del mouse su dispositivo mobile : ecco un modo per aggiungere o rimuovere dinamicamente una " can touch" classe al documento in base al tipo di input corrente dell'utente. Funziona anche con dispositivi ibridi in cui l'utente può passare dal tocco al mouse / trackpad:

<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>

Questo è il modo migliore che trovo, inoltre se aumenti il ​​timer a 1000ms puoi anche coprire la pressione prolungata, vedi qui . Roba fantastica!
Lowtechsun,

3

Avevo intenzione di pubblicare la mia soluzione, ma controllando se qualcuno l'aveva già pubblicata, ho scoperto che @Rodney l'ha quasi fatto. Tuttavia, gli è mancato un ultimo cruciale che lo ha reso inappropriato, almeno nel mio caso. Voglio dire, anch'io ho preso la stessa .fakeHoveraggiunta / rimozione di classe tramite mouseentere il mouseleaverilevamento degli eventi, ma da solo, di per sé , si comporta quasi esattamente come "genuino" :hover. Voglio dire: quando tocchi un elemento nella tua tabella, non rileverà che lo hai "lasciato", mantenendo così lo stato "fakehover".

Quello che ho fatto è stato semplicemente ascoltare click , quindi quando "tocco" il pulsante, sparo manualmente a mouseleave.

Si questo è il mio codice finale:

.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();
});

In questo modo mantieni la tua solita hoverfunzionalità quando usi un mouse semplicemente "passando il mouse" sui pulsanti. Bene, quasi tutto: l'unico inconveniente è che, dopo aver fatto clic sul pulsante con il mouse, non sarà nello hoverstato. Proprio come se si fa clic e si toglie rapidamente il puntatore dal pulsante. Ma nel mio caso posso conviverci.


2

Questo è quello che ho escogitato finora dopo aver studiato il resto delle risposte. Dovrebbe essere in grado di supportare utenti solo touch, solo mouse o ibridi.

Crea una classe hover separata per l'effetto hover. Per impostazione predefinita, aggiungi questa classe al passaggio del mouse sul nostro pulsante.

Non vogliamo rilevare la presenza del supporto touch e disabilitare tutti gli effetti hover fin dall'inizio. Come menzionato da altri, i dispositivi ibridi stanno guadagnando popolarità; le persone possono avere il supporto per il tocco ma vogliono usare un mouse e viceversa. Pertanto, rimuovere la classe al passaggio del mouse solo quando l'utente tocca effettivamente il pulsante.

Il prossimo problema è: cosa succede se l'utente desidera tornare a utilizzare un mouse dopo aver toccato il pulsante? Per risolverlo, dobbiamo trovare un momento opportuno per aggiungere nuovamente la classe hover che abbiamo rimosso.

Tuttavia, non è possibile aggiungerlo immediatamente dopo averlo rimosso, poiché lo stato al passaggio del mouse è ancora attivo. Potremmo non voler distruggere e ricreare anche l'intero pulsante.

Quindi, ho pensato di utilizzare un algoritmo di attesa (utilizzando setInterval) per verificare lo stato al passaggio del mouse. Una volta disattivato lo stato al passaggio del mouse, possiamo quindi aggiungere nuovamente la classe al passaggio del mouse e interrompere l'attesa di occupato, riportandoci allo stato originale in cui l'utente può utilizzare il mouse o il tocco.

So che l'attesa non è eccezionale, ma non sono sicuro che ci sia un evento appropriato. Ho preso in considerazione l'idea di aggiungerlo di nuovo nell'evento di mouseleave, ma non era molto robusto. Ad esempio, quando viene visualizzato un avviso dopo che è stato toccato il pulsante, la posizione del mouse si sposta ma l'evento di mouseleave non viene attivato.

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>

Modifica: un altro approccio che ho provato è quello di chiamare e.preventDefault()intouchstart o ontouchend. Sembra fermare l'effetto hover quando si tocca il pulsante, ma arresta anche l'animazione del clic del pulsante e impedisce che la funzione onclick venga chiamata quando si tocca il pulsante, quindi è necessario chiamarli manualmente nel gestore intouchstart o intouchend. Non è una soluzione molto pulita.


1

Mi è stato utile: 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");
                    }
                }
            }
        }
    }
}

È necessario chiamare hoverTouchUnstick () una volta dal gestore globale di eventi ontouchstart. E questa soluzione funzionerebbe perfettamente.
Jusid,

1

Aggiungi questo codice JS alla tua pagina:

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

ora nel tuo CSS prima di ogni passaggio del mouse aggiungi la classe al passaggio del mouse in questo modo:

.hover .foo:hover {}

Se il dispositivo è a contatto, la classe del corpo sarà vuota, altrimenti la sua classe sarà al passaggio del mouse e verranno applicate le regole!


Non ha funzionato per me, ma questo ha fatto:document.body.className = 'ontouchstart' in window ? '' : 'hover';
drskullster,

1

Potrei aggiungere una classe no-hover per ogni pulsante e rendere il mio CSS simile a> this: button: not (.no-hover): hover {background-color: blue; } ma probabilmente è piuttosto negativo per le prestazioni e non gestisce> dispositivi come il Chromebook Pixel (che ha sia un touchscreen che un mouse)> correttamente.

Questo è il punto di partenza giusto. Passaggio successivo: applicare / rimuovere la classe nohover sui seguenti eventi (demo con jQuery)

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

Avviso: se si desidera applicare altre classi al buttonelement, il: not (.nohover) nel CSS non funzionerà più come previsto. Quindi devi aggiungere una definizione separata con valore predefinito e! Tag importante per sovrascrivere lo stile hover: .nohover {background-color: white! Important}

Questo dovrebbe anche gestire dispositivi come il Chromebook Pixel (che ha sia un touchscreen che un mouse) correttamente! E non penso che questo sia un grande killer delle prestazioni ...


1

Una soluzione che ha funzionato per me:

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

Aggiungi questo codice al tuo foglio di stile.

Volevo liberarmi dello sfondo grigio che appare su iOS Safari quando si fa clic su un collegamento. Ma sembra fare di più. Ora facendo clic su un pulsante (con una :hoverpseudoclasse!) Si apre subito! L'ho provato solo su un iPad, non so se funzionerà su altri dispositivi.


1

Penso di aver trovato una soluzione elegante (minimo js) per un problema simile:

Usando jQuery, puoi attivare l'hover sul corpo (o qualsiasi altro elemento), usando .mouseover()

Quindi allego semplicemente questo gestore ontouchendall'evento dell'elemento in questo modo:

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

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

Questo, tuttavia, rimuove solo: passa il mouse sulla pseudoclasse dall'elemento dopo che è stato attivato qualche altro evento di tocco, come scorrere o un altro tocco


1
Per il tuo frammento di codice, il quadrato rimane ancora rosa dopo averlo toccato. Immagino che non hai davvero risolto il problema posto in questa domanda?
Kevin Lee,

Questa soluzione non funziona. Innanzitutto, hai usato il metodo sbagliato per invocare un evento, dovresti usare .trigger () . In secondo luogo, non funziona su Safari mobile in entrambi i casi.
xHocquet,

1

Ho una bella soluzione che vorrei condividere. Innanzitutto è necessario rilevare se l'utente è mobile come questo:

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

Quindi aggiungi solo:

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

E nei CSS:

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

2
Non funziona su dispositivi ibridi, ad esempio PC con touchscreen Windows.
cspolton,

1

Ho affrontato il problema simile, la mia applicazione era compatibile con tutte le dimensioni dello schermo ha avuto un sacco di effetti al passaggio del mouse nella dimensione dello schermo del desktop dispositivi basati / mouse, e in seguito mi sono reso conto che i dispositivi basati sul tocco stavano causando una condizione nota come appiccicosa -hover ed è stato un ostacolo per il corretto funzionamento dell'app per gli utenti di dispositivi touch-based.

Stavamo usando SCSS nella nostra app. e ho definito un mixin per prendermi cura del dispositivo touch based.

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

e poi ho inserito tutte le mie classi css nello snippet di seguito indicato.

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

Ad esempio, abbiamo tenuto una lezione per animare un'icona e che si attivava una volta che passavamo il mouse sopra l'icona come puoi vederla dal CSS, ma in un dispositivo basato sul tocco veniva influenzata da un effetto appiccicoso al passaggio del mouse e poi l'ho inserito all'interno di @ include hover-support () al fine di garantire che l'hover si applichi solo ai dispositivi che supportano l'hover.

@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

Ecco un semplice codice JavaScript che non richiede allo sviluppatore di modificare CSS o scrivere nuove regole CSS. Ho scritto questo per i pulsanti Bootstrap con class="btn", ma funzionerà con qualsiasi pulsante che abbia un nome di classe specifico.

I passaggi sono:

  1. determinare se si tratta di un dispositivo touch
  2. in caso affermativo, scorrere su ogni regola CSS in document.styleSheets
  3. elimina qualsiasi regola contenente sia .btne:hover

L'eliminazione di tutte le .btn :hoverregole CSS garantisce che non ci sia alcun effetto di hover visivo su un pulsante.

Passaggio 1: Rileva dispositivo touch

Controlla la media query per la presenza di (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;
    };

Passaggio 2: eliminare le regole CSS contenenti `btn` e`: hover`

    /**
     * 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;
    }

Il codice completo è su GitHub e npm .

Demo live su terrymorse.com .


Questo non rimuove anche l'effetto hover per i dispositivi touchscreen con mouse / trackpad?
Jensei

@Jensei Forse. Le regole al passaggio del mouse vengono rimosse se il dispositivo corrisponde @media (hover:none)o quando l'utente tocca lo schermo per la prima volta. Puoi provarlo sulla pagina della demo live per essere sicuro.
Terrymorse

0

È possibile impostare il colore di sfondo sullo :activestato e fornire :focus lo sfondo predefinito.

se si imposta il colore di sfondo tramite onfocus/ontouch, lo stile del colore rimane quando lo :focusstato è passato.
È necessario anche un reset onblurper ripristinare il defg bg quando si perde la messa a fuoco.


Ma vorrei mantenere l'effetto hover per gli utenti del mouse.
Chris,

: hover e: active può ricevere lo stesso CSS, è attivo: focus hai il problema. In realtà, se si imposta il colore di sfondo tramite onfocus, lo stile del colore rimane una volta che la messa a fuoco è andata. hai bisogno di un reset anche su onlur per ripristinare defaut bg
G-Cyrillus,

0

Questo ha funzionato per me: mettere lo styling hover in una nuova classe

.fakehover {background: red}

Quindi aggiungere / rimuovere la classe come e quando richiesto

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

Ripetere l'operazione per eventi touchstart e touchend. O qualunque evento ti piaccia per ottenere il risultato desiderato, ad esempio volevo che l'effetto hover fosse attivato su un touchscreen.


0

Basato sulla risposta di Darren Cooks che funziona anche se si sposta il dito su un altro elemento.

Vedi Trova il dito dell'elemento attivo durante un evento touchend

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

Puoi provare in questo modo.

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

Quello che ho fatto finora nei miei progetti è stato di ripristinare le :hovermodifiche sui dispositivi touch:

.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;
    }
}

Tutti i nomi delle classi e i colori nominati solo a scopo dimostrativo ;-)


0

Funziona perfettamente in 2 passaggi.

  1. Imposta il tuo body tag in questo modo <body ontouchstart="">. Non sono un fan di questo "hack", ma consente a Safari su iOS di reagire istantaneamente ai tocchi. Non so come, ma funziona.

  2. Imposta la tua classe toccabile in questo modo:

    // 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;
            }
        }
    }

Puoi anche rimuovere qualsiasi animazione della tua classe toccabile. Android Chrome sembra essere un po 'più lento di iOS.

Ciò comporterà anche l'applicazione dello stato attivo se l'utente scorre la pagina mentre tocca la classe.


0

Alcuni dei :hover :focus :activeproblemi appiccicosi o bloccati sui dispositivi mobili possono essere causati dalla mancanza <meta name="viewport" content="width=device-width">mentre i browser tentano di manipolare lo schermo.


0

La soluzione per me era dopo che il touchend era clonare e sostituire il nodo ... odio farlo ma anche provare a ridipingere l'elemento con offsetHeight non funzionava

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

Alla fine questo non ha funzionato per me ... il mio caso avrei dovuto clonare un intero ES6 che è stato esteso e diversi ascoltatori di eventi e ha iniziato a diventare complicato per risolvere una cosa così piccola.
Vietare il

0

Può essere realizzato scambiando una classe HTML. Dovrebbe essere meno soggetto a problemi tecnici rispetto alla rimozione dell'intero elemento, in particolare con collegamenti di immagini di grandi dimensioni, ecc.

Possiamo anche decidere se vogliamo che gli stati al passaggio del mouse vengano attivati ​​durante lo scorrimento con touch (touchmove) o anche aggiungere un timeout per ritardarli.

L'unica modifica significativa nel nostro codice sarà l'utilizzo di ulteriori classi HTML, ad esempio <a class='hover'></a>su elementi che implementano il nuovo comportamento.

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 (con jQuery)

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

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

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

Esempio

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

-

Tuttavia, non ho alcun dispositivo con il mouse e il tocco per testarlo correttamente.


0

Dal 2020 è possibile aggiungere stili al passaggio del mouse all'interno di media query

@media (hover: hover) and (pointer: fine) {
    /* css hover class/style */
}

Questa media query indica che gli stili funzioneranno su browser che non emulano: passa il mouse quindi NON funzioneranno su browser touch.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.