Comment éviter les effets de survol collant pour les boutons sur les appareils tactiles


144

J'ai créé un carrousel avec un bouton précédent et suivant qui sont toujours visibles. Ces boutons ont un état de survol, ils deviennent bleus. Sur les appareils tactiles, comme l'iPad, l'état de survol est collant, de sorte que le bouton reste bleu après avoir appuyé dessus. Je ne veux pas de ça.

  • Je pourrais ajouter une no-hoverclasse ontouchendpour chaque bouton et rendre mon CSS comme ceci: button:not(.no-hover):hover { background-color: blue; }mais c'est probablement assez mauvais pour les performances et ne gère pas correctement les appareils comme le Chromebook Pixel (qui a à la fois un écran tactile et une souris).

  • Je pourrais ajouter une touchclasse au documentElementet faire de mon CSS comme ceci: html:not(.touch) button:hover { background-color: blue; }Mais cela ne fonctionne pas non plus correctement sur les appareils à la fois tactiles et souris.

Ce que je préférerais, c'est supprimer l'état de survol ontouchend. Mais cela ne semble pas possible. La focalisation sur un autre élément ne supprime pas l'état de survol. Taper manuellement sur un autre élément le fait, mais je n'arrive pas à déclencher cela en JavaScript.

Toutes les solutions que j'ai trouvées me semblent imparfaites. Y a-t-il une solution parfaite?

Réponses:


55

Vous pouvez supprimer l'état de survol en supprimant temporairement le lien du DOM. Voir http://testbug.handcraft.com/ipad.html


Dans le CSS, vous avez:

:hover {background:red;}

Dans le JS, vous avez:

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

Et puis dans votre HTML vous avez:

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

3
@Chris Bon point, j'ai changé l'exemple pour définir le gestionnaire onclick dans l'événement ontouchend.
Sjoerd Visscher

4
Veuillez envisager d'ajouter un code de démonstration minimal à votre réponse. Merci! stackoverflow.com/help/how-to-answer
2540625

1
@SjoerdVisscher Je l'ai collé. StackOverflow aime que le code soit dans la réponse, car les liens peuvent disparaître. (Et dans ce cas, il fallait non seulement cliquer, mais ensuite visualiser la source et déterminer quels bits sont la technique en question.)
Darren Cook

2
@KevinBorders oui sur certains appareils, le délai entre le retrait et la réinsertion de l'élément peut être très perceptible. Malheureusement, j'ai trouvé sur mon appareil Android 4.4 que cela ne fonctionnait pas sans setTimeout.
Rodney

1
L'idée est intéressante, mais je l'ai trouvée un peu saccadée et pas largement prise en charge sur tous les appareils tactiles. Je préférerais une solution moins invasive basée sur la détection du support tactile et le CSS pur comme ce stackoverflow.com/a/39787268/885464
Lorenzo Polidori

83

Une fois que CSS Media Queries Level 4 est implémenté, vous pourrez le faire:

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

Ou en anglais: "Si le navigateur prend en charge le survol correct / vrai / réel / non émulé (par exemple, il a un périphérique d'entrée principal semblable à une souris), appliquez ce style lorsque vous buttonsurvolez s."

Étant donné que cette partie de Media Queries Level 4 n'a jusqu'à présent été implémentée que dans Chrome de pointe, j'ai écrit un polyfill pour y faire face. En l'utilisant, vous pouvez transformer le CSS futuriste ci-dessus en:

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

(Une variante de la .no-touchtechnique) Et puis en utilisant du JavaScript côté client du même polyfill qui détecte la prise en charge du survol, vous pouvez basculer la présence de la my-true-hoverclasse en conséquence:

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

Merci! Pour mes besoins, cela semble être pris en charge dans la plupart des navigateurs caniuse.com/#search=media%20queries et fonctionne à merveille , merci!
ragamufin

3
Vous devez plutôt regarder caniuse.com/#feat=css-media-interaction et vous verrez qu'il n'est pas pris en charge dans Firefox et IE11: (vous avez donc besoin du polyfill
CherryDT

Il semble que le polyfill ne soit plus pris en charge (le dépôt est archivé) et qu'il nécessite jQuery ...
amoebe

Ceci est maintenant largement pris en charge dans les navigateurs mobiles et fonctionne à merveille. Je pense que ce devrait être la réponse acceptée.
Trevor Burnham

C'est certainement la réponse la plus simple à mettre en œuvre et la meilleure. Fonctionne dans Firefox sur Android Mobile et PC. Je ne suis pas sûr des périphériques à double contact et souris.
HalfMens

28

C'est un problème courant sans solution parfaite. Le comportement de survol est utile avec une souris et surtout nuisible au toucher. Le problème est aggravé par des appareils prenant en charge le toucher et la souris (simultanément, rien de moins!) Comme le Chromebook Pixel et Surface.

La solution la plus propre que j'ai trouvée est de n'activer le comportement de survol que si l'appareil n'est pas réputé prendre en charge la saisie tactile.

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

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

Certes, vous perdez le survol sur les appareils qui peuvent le prendre en charge. Cependant, parfois, le survol a plus d'impact que le lien lui-même, par exemple, vous souhaitez peut-être afficher un menu lorsqu'un élément est survolé. Cette approche vous permet de tester l'existence du toucher et peut-être de joindre conditionnellement un événement différent.

J'ai testé cela sur iPhone, iPad, Chromebook Pixel, Surface et une variété d'appareils Android. Je ne peux pas garantir que cela fonctionnera lorsqu'une entrée tactile USB générique (comme un stylet) est ajoutée au mix.


1
Génial, cela a fonctionné pour moi, contrairement à la réponse wiki / Darren Cook de la communauté.
Jannik

1
Bonne réponse. C'est une solution similaire: stackoverflow.com/a/39787268/885464
Lorenzo Polidori

11

Avec Modernizr, vous pouvez cibler vos survols spécifiquement pour les appareils sans contact:

(Remarque: cela ne fonctionne pas sur le système d'extraits de code de StackOverflow, vérifiez plutôt le 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;
}

Notez que cela :activen'a pas besoin d'être ciblé .no-touchcar il fonctionne comme prévu sur les mobiles et les ordinateurs de bureau.


C'est la meilleure réponse IMO MAIS l'exemple est incorrect. Il affiche le même état de survol pour les appareils tactiles et non tactiles. Il ne doit appliquer l'état de survol que s'il .no-touchest présent sur la htmlbalise. Sinon, cette réponse obtient mon sceau d'approbation.
morrisbret

2
Le problème est que maintenant que les appareils compatibles avec la souris et dotés d'écrans tactiles sont partout, vous ne pouvez plus vraiment compter sur cette méthode. Cependant, je ne vois pas grand-chose d'autre façon de le faire ... c'est tout un dilemme
dudewad

Je suppose qu'une façon de le faire serait d'utiliser à la fois Modernizr et une bibliothèque telle que mobile-detect.js pour s'assurer qu'il s'agit d'un téléphone ou d'une tablette.
Gavin

Vous êtes l'homme sauveur merci beaucoup cela a parfaitement fonctionné pour les appareils mobiles
Shivam

9

Vous pouvez remplacer l'effet de survol pour les appareils qui ne prennent pas en charge le survol. Comme:

.my-thing {
    color: #BADA55;
}

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

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

Testé et vérifié sur iOS 12

Pointe du chapeau à https://stackoverflow.com/a/50285058/178959 pour le signaler.


C'est la solution la plus moderne, aucune manipulation javascript ou DOM requise, prend en charge l'intégralité du navigateur (sauf IE) et devrait être la réponse acceptée.
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();
});

Vous pouvez améliorer cette réponse en utilisant un on () au lieu d'un clic (). En supprimant l'élément du DOM et en le rattachant, j'ai perdu mes événements de clic. Lorsque j'ai réécrit ma fonction avec le, la liaison à l'élément, puis la suppression et l'ajout ont fonctionné. Par exemple: `$ ('body'). On ('click', '# elementwithhover', function () {// clone, insertafter, remove}); Je voterai si vous apportez ce changement.
Will Lanni

le clone true préserve l'événement click sur le nouvel elemenet à la place de l'élément avec le survol bloqué. l'élément d'origine est supprimé du dom après son clonage.
Verard Sloggett

génial bro, 10x
Kaloyan Stamatov

Des heures de recherche d'un correctif et cela a finalement fourni un. Mille mercis!
phil917

8

De 4 façons de gérer le survol collant sur mobile : Voici un moyen d'ajouter ou de supprimer dynamiquement une can touchclasse " " au document en fonction du type d'entrée actuel de l'utilisateur. Il fonctionne également avec les appareils hybrides où l'utilisateur peut basculer entre le tactile et une souris / 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>

C'est le meilleur moyen que je trouve, et si vous augmentez la minuterie à 1000 ms, vous pouvez également couvrir la pression longue, voir ici . Super truc!
lowtechsun

3

J'allais publier ma propre solution, mais en vérifiant si quelqu'un l'avait déjà postée, j'ai trouvé que @Rodney l'avait presque fait. Cependant, il a raté une dernière étape cruciale qui l'a rendu unie, du moins dans mon cas. Je veux dire, moi aussi j'ai pris la même .fakeHoverclasse d'ajout / suppression via mouseenteret mouseleavedétection d'événement, mais cela seul, en soi , agit presque exactement comme "authentique" :hover. Je veux dire: lorsque vous appuyez sur un élément de votre table, il ne détectera pas que vous l'avez "quitté" - gardant ainsi l'état "fakehover".

Ce que j'ai fait était simplement d'écouter click, aussi, alors quand je "tape" sur le bouton, je déclenche manuellement un mouseleave.

Si c'est mon code final:

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

De cette façon, vous conservez votre hoverfonctionnalité habituelle lorsque vous utilisez une souris en "survolant" simplement vos boutons. Eh bien, presque tout: le seul inconvénient est que, après avoir cliqué sur le bouton avec la souris, il ne sera pas en hoverétat. Un peu comme si vous cliquiez et retiriez rapidement le pointeur du bouton. Mais dans mon cas, je peux vivre avec ça.


2

C'est ce que j'ai trouvé jusqu'ici après avoir étudié le reste des réponses. Il devrait pouvoir prendre en charge les utilisateurs tactiles uniquement, souris uniquement ou hybrides.

Créez une classe de survol distincte pour l'effet de survol. Par défaut, ajoutez cette classe de survol à notre bouton.

Nous ne voulons pas détecter la présence du support tactile et désactiver tous les effets de survol dès le début. Comme mentionné par d'autres, les appareils hybrides gagnent en popularité; les gens peuvent avoir un support tactile mais veulent utiliser une souris et vice versa. Par conséquent, supprimez la classe de survol uniquement lorsque l'utilisateur touche réellement le bouton.

Le problème suivant est le suivant: que se passe-t-il si l'utilisateur souhaite revenir à l'utilisation d'une souris après avoir touché le bouton? Pour résoudre cela, nous devons trouver un moment opportun pour rajouter la classe de survol que nous avons supprimée.

Cependant, nous ne pouvons pas le rajouter immédiatement après l'avoir supprimé, car l'état de survol est toujours actif. Nous pouvons également ne pas vouloir détruire et recréer le bouton entier.

J'ai donc pensé à utiliser un algorithme d'attente occupé (en utilisant setInterval) pour vérifier l'état de survol. Une fois l'état de survol désactivé, nous pouvons ensuite rajouter la classe de survol et arrêter l'attente occupée, nous ramenant à l'état d'origine où l'utilisateur peut utiliser la souris ou le toucher.

Je sais que l'attente occupée n'est pas terrible, mais je ne sais pas s'il y a un événement approprié. J'ai envisagé de l'ajouter à l'événement mouseleave, mais ce n'était pas très robuste. Par exemple, lorsqu'une alerte apparaît après avoir touché le bouton, la position de la souris change mais l'événement mouseleave n'est pas déclenché.

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>

Edit: Une autre approche que j'ai essayée est d'appeler e.preventDefault()dans ontouchstart ou ontouchend. Il semble arrêter l'effet de survol lorsque le bouton est touché, mais il arrête également l'animation de clic sur le bouton et empêche la fonction onclick d'être appelée lorsque le bouton est touché, vous devez donc les appeler manuellement dans le gestionnaire ontouchstart ou ontouchend. Pas une solution très propre.


1

Cela m'a été utile: lien

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

Vous devez appeler hoverTouchUnstick () une fois à partir du gestionnaire d'événements global ontouchstart. Et cette solution fonctionnerait parfaitement.
Jusid

1

Ajoutez ce code JS à votre page:

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

maintenant dans votre CSS avant chaque survol, ajoutez la classe hover comme ceci:

.hover .foo:hover {}

Si l'appareil est tactile, la classe body sera vide, sinon sa classe sera survolée et les règles seront appliquées!


Cela n'a pas fonctionné pour moi, mais cela a fonctionné:document.body.className = 'ontouchstart' in window ? '' : 'hover';
drskullster

1

Je pourrais ajouter une classe sans survol ontouchend pour chaque bouton, et rendre mon CSS comme> this: button: not (.no-hover): hover {background-color: blue; } mais c'est probablement assez mauvais pour les performances, et ne gère pas> correctement les appareils comme le Chromebook Pixel (qui a à la fois un écran tactile et une souris).

C'est le bon point de départ. Étape suivante: appliquer / supprimer la classe nohover sur les événements suivants (démo avec jQuery)

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

Remarque: si vous souhaitez appliquer d'autres classes à l'élément de bouton, le: not (.nohover) dans le CSS ne fonctionnera plus comme prévu. Ensuite, vous devez ajouter à la place une définition séparée avec la valeur par défaut et la balise! Important pour remplacer le style de survol: .nohover {background-color: white! Important}

Cela devrait même gérer correctement les appareils comme le Chromebook Pixel (qui possède à la fois un écran tactile et une souris)! Et je ne pense pas que ce soit un tueur de performances majeur ...


1

Une solution qui a fonctionné pour moi:

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

Ajoutez ce code à votre feuille de style.

Je voulais me débarrasser du fond gris qui apparaît sur iOS Safari lorsqu'un lien est cliqué. Mais il semble faire plus. Maintenant, un clic sur un bouton (avec une :hoverpseudoclasse!) S'ouvre tout de suite! Je ne l'ai testé que sur un iPad, je ne sais pas si cela fonctionnera sur d'autres appareils.


1

Je pense avoir trouvé une solution élégante (minimum js) pour un problème similaire:

En utilisant jQuery, vous pouvez déclencher le survol du corps (ou tout autre élément), en utilisant .mouseover()

Donc, j'attache simplement un gestionnaire this à l' ontouchendévénement de l'élément comme ceci:

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

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

Cependant, cela ne supprime que: survolez la pseudo-classe de l'élément après qu'un autre événement tactile a été déclenché, comme un balayage ou un autre toucher


1
Pour votre extrait de code, le carré reste rose après que je l'ai touché. Je suppose que vous n'avez pas vraiment résolu le problème posé dans cette question?
Kevin Lee

Cette solution ne fonctionne pas. Tout d'abord, vous avez utilisé la mauvaise méthode pour appeler un événement an, vous devez utiliser .trigger () . Deuxièmement, ne fonctionne pas sur le safari mobile de toute façon.
xHocquet

1

J'ai une belle solution que je voudrais partager. Vous devez d'abord détecter si l'utilisateur est sur mobile comme ceci:

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

Ensuite, ajoutez simplement:

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

Et en CSS:

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

2
Ne fonctionne pas sur les appareils hybrides, par exemple les PC à écran tactile Windows.
cspolton

1

J'ai traversé le même problème, mon application était compatible pour toutes les tailles d'écran avait beaucoup d'effets de survol dans les appareils basés sur la taille de l'écran de bureau / la souris, et plus tard, j'ai réalisé que les appareils tactiles causaient une condition connue sous le nom de collant -hover et c'était un obstacle pour que l'application fonctionne correctement pour les utilisateurs d'appareils tactiles.

Nous utilisions SCSS dans notre application. et j'ai défini un mixin pour prendre en charge les appareils tactiles.

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

puis j'ai placé toutes mes classes css sous l'extrait de code ci-dessous.

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

Par exemple, nous avions une classe pour animer une icône, et qui se déclenchait une fois que nous survolions l'icône comme vous pouvez le voir à partir de css, mais dans l'appareil tactile, il était affecté par l'effet de survol collant, puis je l'ai placé à l'intérieur @ include hover-support () afin de garantir que le survol s'applique uniquement aux appareils prenant en charge le survol.

@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

Voici un code JavaScript simple qui n'oblige pas le développeur à modifier le CSS ou à écrire de nouvelles règles CSS. J'ai écrit ceci pour les boutons Bootstrap avec class="btn", mais cela fonctionnera avec n'importe quel bouton qui a un nom de classe spécifique.

Les étapes sont:

  1. déterminer s'il s'agit d'un appareil tactile
  2. si c'est le cas, effectuez une itération sur chaque règle CSS dans document.styleSheets
  3. supprimer toute règle contenant à la fois .btnet:hover

L'élimination de toutes les .btn :hoverrègles CSS garantit qu'il n'y aura aucun effet de survol visuel sur un bouton.

Étape 1: Détecter le périphérique tactile

Vérifiez la requête multimédia pour la présence de (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;
    };

Étape 2: Supprimer les règles CSS contenant `btn` et`: 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;
    }

Le code complet est sur GitHub et npm .

Démo en direct sur terrymorse.com .


Cela ne supprime-t-il pas également l'effet de survol pour les appareils à écran tactile avec souris / trackpad?
Jensei

@Jensei Peut-être. Les règles de survol sont supprimées si l'appareil correspond @media (hover:none)ou lorsque l'utilisateur touche l'écran pour la première fois. Vous pouvez l'essayer sur la page de démonstration en direct pour en être sûr.
terrymorse

0

Vous pouvez définir la couleur d'arrière-plan sur l' :activeétat et donner :focus l'arrière-plan par défaut.

si vous définissez la couleur d'arrière-plan via onfocus/ontouch, le style de couleur reste une fois l' :focusétat disparu.
Vous avez également besoin d'une réinitialisation onblurpour restaurer le bg par défaut lorsque la mise au point est perdue.


Mais je voudrais conserver l'effet de survol pour les utilisateurs de souris.
Chris

: hover et: active peuvent recevoir le même CSS, c'est sur: focus vous avez le problème. En fait, si vous définissez la couleur d'arrière-plan via onfocus, le style de couleur reste une fois la mise au point terminée. vous avez également besoin d'une réinitialisation sur onlur pour restaurer defaut bg
G-Cyrillus

0

Cela a fonctionné pour moi: mettez le style de survol dans une nouvelle classe

.fakehover {background: red}

Ensuite, ajoutez / supprimez la classe au fur et à mesure des besoins

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

Répétez pour les événements touchstart et touchend. Ou quels que soient les événements que vous souhaitez pour obtenir le résultat souhaité, par exemple, je voulais que l'effet de survol soit basculé sur un écran tactile.


0

Basé sur la réponse de Darren Cooks qui fonctionne également si vous déplacez votre doigt sur un autre élément.

Voir Le doigt de l'élément de recherche est activé pendant un événement 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

Vous pouvez essayer de cette façon.

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

Ce que j'ai fait jusqu'à présent dans mes projets était d'annuler les :hovermodifications sur les appareils tactiles:

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

Tous les noms de classe et les couleurs nommées juste à des fins de démonstration ;-)


0

Cela fonctionne parfaitement en 2 étapes.

  1. Définissez votre balise corporelle comme ceci <body ontouchstart="">. Je ne suis pas fan de ce "hack", mais il permet à Safari sur iOS de réagir instantanément aux touches. Je ne sais pas comment, mais ça marche.

  2. Configurez votre classe tactile comme ceci:

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

Vous pouvez également supprimer toute animation de votre classe palpable. Android Chrome semble être un peu plus lent qu'iOS.

Cela entraînera également l'application de l'état actif si l'utilisateur fait défiler la page tout en touchant votre classe.


0

Certains des :hover :focus :activeproblèmes persistants ou bloqués sur les appareils mobiles peuvent être causés par l'absence <meta name="viewport" content="width=device-width">lorsque les navigateurs tentent de manipuler l'écran.


0

La solution pour moi était après touchend était de cloner et de remplacer le nœud ... je déteste faire cela mais même essayer de repeindre l'élément avec offsetHeight ne fonctionnait pas

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

En fin de compte, cela n'a pas fonctionné pour moi ... mon cas, je devrais cloner un ES6 entier qui est étendu et plusieurs écouteurs d'événements et cela a commencé à devenir trop compliqué pour résoudre une si petite chose.
Interdiction le

0

Cela peut être accompli en échangeant une classe HTML. Cela devrait être moins sujet aux problèmes que de supprimer tout l'élément, en particulier avec de grands liens d'image, etc.

Nous pouvons également décider si nous voulons survoler états de soient déclenchés lors du défilement tactile (touchmove) ou même ajouter un délai pour les retarder.

Le seul changement significatif dans notre code sera l'utilisation d'une classe HTML supplémentaire, par exemple <a class='hover'></a>sur les éléments qui implémentent le nouveau comportement.

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

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

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

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

Exemple

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

-

Cependant, je n'ai aucun appareil avec la souris et le toucher pour le tester correctement.


0

À partir de 2020, vous pouvez ajouter des styles de survol dans la requête multimédia

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

Cette requête multimédia indique que les styles fonctionneront sur les navigateurs qui n'émulent pas: survolez donc cela ne fonctionnera PAS sur les navigateurs tactiles.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.