Puis-je désactiver un effet CSS: hover via JavaScript?

99

J'essaie d'empêcher le navigateur d'utiliser l' :hovereffet du CSS, via JavaScript.

J'ai défini les styles aet a:hoverdans mon CSS, car je veux un effet de survol, si JS n'est pas disponible. Mais si JS est disponible, je souhaite remplacer mon effet de survol CSS par un effet plus lisse (en utilisant le plugin de couleur jQuery par exemple.)

J'ai essayé ceci:

$("ul#mainFilter a").hover(
     function(e){ e.preventDefault(); ...do my stuff... }, 
     function(e){ e.preventDefault(); ...do my stuff... });

Je l'ai aussi essayé avec return false;, mais cela ne fonctionne pas.

Voici un exemple de mon problème: http://jsfiddle.net/4rEzz/ . Le lien devrait simplement s'estomper sans devenir gris.

Comme mentionné par fudgey, une solution de contournement serait de réinitialiser les styles de survol en utilisant, .css()mais je devrais écraser chaque propriété, spécifiée dans le CSS (voir ici: http://jsfiddle.net/raPeX/1/ ). Je recherche une solution générique.

Est-ce que quelqu'un sait comment faire ça?

PS: Je ne veux pas écraser tous les styles que j'ai définis pour le survol.

moi
la source

Réponses:

136

Il n'y a pas de solution générique JavaScript pure, j'en ai peur. JavaScript ne peut pas désactiver l' :hoverétat CSS lui-même.

Vous pouvez cependant essayer la solution alternative suivante. Si cela ne vous dérange pas de vous amuser un peu dans votre HTML et votre CSS, cela vous évite d'avoir à réinitialiser chaque propriété CSS manuellement via JavaScript.

HTML

<body class="nojQuery">

CSS

/* Limit the hover styles in your CSS so that they only apply when the nojQuery 
class is present */

body.nojQuery ul#mainFilter a:hover {
    /* CSS-only hover styles go here */
}

JavaScript

// When jQuery kicks in, remove the nojQuery class from the <body> element, thus
// making the CSS hover styles disappear.

$(function(){}
    $('body').removeClass('nojQuery');
)
Paul D. Waite
la source
5
J'aime mieux cette solution que les solutions noscript car cela fonctionne lorsque le CSS est entièrement contenu dans des fichiers externes, et cela fonctionne également pendant le chargement de la page, si le CSS se charge en premier mais que le JS ne se charge que plus tard. L'utilisation de jQuery pour «améliorer progressivement» les choses entraîne souvent des pages qui ne fonctionnent pas bien si vous cliquez sur des éléments avant la fin du chargement. Même avec un navigateur rapide sur un lien rapide, je vois souvent cela.
Mr. Shiny and New 安 宇
@Monsieur. Shiny and New: Je suis d'accord, j'aime ça mieux que ma solution aussi! Je ne sais pas pourquoi je n'ai pas remarqué l'élégance de celui-ci avant ...
Josh
3
«J'aime mieux cette solution que les solutions noscript parce que cela fonctionne lorsque le CSS est entièrement contenu dans des fichiers externes» - la <noscript>solution aussi. Vous mettez simplement des <link>balises dans votre <noscript>, au lieu de <style>balises. Ma solution vous permet de tout conserver dans un seul fichier de feuille de style plutôt que dans plusieurs fichiers.
Paul D.Waite
ce n'est pas exactement ce que je cherchais mais je pense que cette solution est le meilleur compromis! Merci à vous tous
meo
vous pouvez également copier le même style avec un nom différent et en utilisant jquery, sélectionnez tous les éléments avec cette classe et supprimez la classe et remplacez-la par la classe de copie.
chepe263
14

Utilisez une deuxième classe à laquelle seul le survol est attribué:

HTML

 <a class="myclass myclass_hover" href="#">My anchor</a>

CSS

 .myclass { 
   /* all anchor styles */
 }
 .myclass_hover:hover {
   /* example color */
   color:#00A;
 }

Vous pouvez maintenant utiliser Jquery pour supprimer la classe, par exemple si l'élément a été cliqué:

JQUERY

 $('.myclass').click( function(e) {
    e.preventDefault();
    $(this).removeClass('myclass_hover');
 });

J'espère que cette réponse est utile.

Kai Noack
la source
3
plus 1. ce n'est pas orthodoxe, mais résout le problème d'une manière assez sublime.
jim tollan
11

Vous pouvez manipuler les feuilles de style et les règles de feuille de style elles-mêmes avec javascript

var sheetCount = document.styleSheets.length;
var lastSheet = document.styleSheets[sheetCount-1];
var ruleCount;
if (lastSheet.cssRules) { // Firefox uses 'cssRules'
    ruleCount = lastSheet.cssRules.length;
}
else if (lastSheet.rules) { / /IE uses 'rules'
    ruleCount = lastSheet.rules.length;
}
var newRule = "a:hover { text-decoration: none !important; color: #000 !important; }";
// insert as the last rule in the last sheet so it
// overrides (not overwrites) previous definitions
lastSheet.insertRule(newRule, ruleCount);

Rendre les attributs! Importants et en faire la toute dernière définition CSS devrait remplacer toute définition précédente, à moins qu'elle ne soit plus spécifiquement ciblée. Vous devrez peut-être insérer plus de règles dans ce cas.

Stephen P
la source
1
Ou vous pouvez mettre toutes les règles noscript dans une seule feuille de style, puis désactiver la feuille de style de javascript.
Sean Hogan
2
Ou mettez votre <link>balise de feuille de style noscript dans un <noscript>élément? Cela fonctionnerait, non?
Paul D.Waite
1
Ou supprimez la règle "offensante": developer.mozilla.org/en/DOM/stylesheet.deleteRule
RoToRa
1
Même IE5 peut le faire. Sa méthode est appelée différemment, mais elle devrait fonctionner: msdn.microsoft.com/en-us/library/ms531195%28v=vs.85%29.aspx . Je n'ai pas vérifié d'autres navigateurs, mais je suppose que tous les navigateurs modernes implémentent la norme.
RoToRa
Dans Firefox, je reçoisError: The operation is insecure.
Alex W
11

Ceci est similaire à la réponse d'aSeptik, mais qu'en est-il de cette approche? Enveloppez le code CSS que vous souhaitez désactiver à l'aide de JavaScript dans des <noscript>balises. De cette façon, si javaScript est désactivé, le CSS :hoversera utilisé, sinon l'effet JavaScript sera utilisé.

Exemple:

<noscript>
<style type="text/css">
ul#mainFilter a:hover {
  /* some CSS attributes here */
}
</style>
</noscript>
<script type="text/javascript">
$("ul#mainFilter a").hover(
     function(o){ /* ...do your stuff... */ }, 
     function(o){ /* ...do your stuff... */ });
</script>
Josh
la source
4

J'ai utilisé l' not()opérateur CSS et la addClass()fonction de jQuery . Voici un exemple, lorsque vous cliquez sur un élément de la liste, il ne survolera plus:

Par exemple:

HTML

<ul class="vegies">
    <li>Onion</li>
    <li>Potato</li>
    <li>Lettuce</li>
<ul>

CSS

.vegies li:not(.no-hover):hover { color: blue; }

jQuery

$('.vegies li').click( function(){
    $(this).addClass('no-hover');
});
ColdTuna
la source
3

J'utiliserais CSS pour empêcher l'événement: hover de modifier l'apparence du lien.

a{
  font:normal 12px/15px arial,verdana,sans-serif;
  color:#000;
  text-decoration:none;
}

Ce simple CSS signifie que les liens seront toujours noirs et non soulignés. Je ne peux pas dire à partir de la question si le changement d'apparence est la seule chose que vous voulez contrôler.

Christopher Altman
la source
c'est bien qu'il y ait un effet: hover si JS n'est pas disponible sur un client. Mais si c'est le cas, je dois l'écraser. J'ai défini une classe: hover dans mon css, je veux juste la désactiver.
meo
@meo: Vous ne pouvez pas désactiver les classes CSS psuedo, mais vous pouvez les remplacer en définissant tous les styles de lien pour avoir la même apparence / les mêmes paramètres. Cette réponse et ma réponse le font, mais de manière différente.
Mottie
3

Je recommanderais de remplacer toutes les :hoverpropriétés :activelorsque vous détectez que l'appareil prend en charge le toucher. Appelez simplement cette fonction lorsque vous procédez ainsi touch().

function touch() {
  if ('ontouchstart' in document.documentElement) {
    for (var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) {
      var sheet = document.styleSheets[sheetI];
      if (sheet.cssRules) {
        for (var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) {
          var rule = sheet.cssRules[ruleI];

          if (rule.selectorText) {
            rule.selectorText = rule.selectorText.replace(':hover', ':active');
          }
        }
      }
    }
  }
}
Shobhit Sharma
la source
Fonctionne très bien pour moi. Merci!
Inversion
1

Essayez simplement de définir la couleur du lien:

$("ul#mainFilter a").css('color','#000');

Edit: ou mieux encore, utilisez le CSS, comme Christopher l'a suggéré

Mottie
la source
jsfiddle.net/raPeX J'ai fait un exemple. Cela fonctionne mais c'est un peu stupide de faire ça. je devrais récupérer chaque valeur CSS et les ajouter comme style? Il doit y avoir un meilleur moyen. Je ne veux pas faire ça. mais +1 pour l'indice
meo
Salut Meo, non non, mon code ci-dessus ciblait un lien spécifique car c'est ce que je pensais que vous vouliez. Vous pouvez généraliser davantage en utilisant simplement aau lieu de ul#mainFilter asi c'est ce que vous voulez dire, ou dites-vous que chaque lien sur la page est d'une couleur différente?
Mottie
J'ai mis à jour votre démo, avec des commentaires, pour vous montrer ce que je veux dire: jsfiddle.net/raPeX/2
Mottie
Je l'ai déjà merci. Mais le problème est qu'il n'y a pas que la couleur qui change sur mon survol, parfois c'est l'arrière-plan, la bordure, parfois même la hauteur de la ligne. C'est pourquoi il serait plus facile pour moi d'empêcher simplement le survol, de remplacer chaque effet de survol.
meo
Correctif partiel pour cette idée: vous pouvez créer css une règle qui sélectionne pour a.jsOverride:hovercela remplace toutes les caractéristiques css, de sorte que les js devraient simplement ajouter cette jsOverrideclasse à tous les liens lorsque la page se charge ...
grossvogel
1

En fait, une autre façon de résoudre ce problème pourrait être d'écraser le CSS avec insertRule.

Il donne la possibilité d'injecter des règles CSS dans une feuille de style existante / nouvelle. Dans mon exemple concret, cela ressemblerait à ceci:

//creates a new `style` element in the document
var sheet = (function(){
  var style = document.createElement("style");
  // WebKit hack :(
  style.appendChild(document.createTextNode(""));
  // Add the <style> element to the page
  document.head.appendChild(style);
  return style.sheet;
})();

//add the actual rules to it
sheet.insertRule(
 "ul#mainFilter a:hover { color: #0000EE }" , 0
);

Démo avec mon exemple original de 4 ans: http://jsfiddle.net/raPeX/21/

moi
la source