meo
meo

Reputation: 31259

Can I disable a CSS :hover effect via JavaScript?

I’m trying to prevent the browser from using the :hover effect of the CSS, via JavaScript.

I have set the a and a:hover styles in my CSS, because I want a hover effect, if JS isn’t available. But if JS is available, I want to overwrite my CSS hover effect with a smoother one (using the jQuery color plugin for example.)

I tried this:

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

I also tried it with return false;, but it does not work.

Here is an example of my problem: http://jsfiddle.net/4rEzz/. The link should just fade without getting gray.

As mentioned by fudgey, a workaround would be to reset the hover styles using .css() but I would have to overwrite every single property, specified in the CSS (see here: http://jsfiddle.net/raPeX/1/ ). I am looking for a generic solution.

Does anyone know how to do this?

PS: I do not want to overwrite every style i have set for the hover.

Upvotes: 115

Views: 184571

Answers (10)

n a
n a

Reputation: 153

This can be realized by pure javascript easily; Try the code below:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    :root {
        --orange-color: #fa8e3f;
        --dark-organge-color: #bd5305;
        --light-color: #fff;
        --dark-color: #000;
        --grey-color: #f2f2f2;
        --transition: all 300ms ease-in-out;
    }
    .quiz-options {
        list-style-type: none;
        margin: 1rem 0;
    }

    .quiz-options li {
        color: var(--light-color);
        background-color: var(--orange-color);
        font-weight: 600;
        border: 3px solid var(--orange-color);
        border-radius: .5rem;
        margin: .7rem 0;
        padding: .4rem 1.2rem;
        box-shadow: 0 4px 0 0 var(--dark-organge-color);
        transition: var(--transition);
    }

    .quiz-options li.enable-hover-active {
        cursor: pointer;
    }

    .quiz-options li.enable-hover-active:hover {
        background-color: var(--grey-color);
        color:var(--dark-color);
        border-color: var(--grey-color);
        box-shadow: 0 4px 0 0 #bbb;
    }

    .quiz-options li.enable-hover-active:active {
        transform: scale(0.97);
    }

    button {
        border: none;
        border-radius: 0.5rem;
        outline: 0;
        font-family: 'Poppins', sans-serif;
        font-size: 1.2rem;
        font-weight: 600;
        padding: .5rem 1rem;
        margin: 0 auto;
        text-transform: uppercase;
        cursor: pointer;
        display: block;
        background-color: var(--grey-color);
        color: var(--dark-color);
        letter-spacing: 2px;
        transition: var(--transition);
        box-shadow: 0 4px 0 0 #bbb;
    }
</style>
<body>
    <ul class="quiz-options">
        <li>option 1</li>
        <li>option 2</li>
        <li>option 3</li>
        <li>option 4</li>
    </ul>
    <button type="button" id="check-answer" onclick="enableHoverActive()">Enable hover & active</button>
    
    <script>
        function enableHoverActive() {
            if (document.getElementById('check-answer').textContent == 'Enable hover & active') {
                document.getElementById('check-answer').textContent = 'Disable hover & active';
                document.querySelectorAll('li').forEach((option) => {
                    option.classList.add('enable-hover-active');
                });
            } else {
                document.getElementById('check-answer').textContent = 'Enable hover & active';
                document.querySelectorAll('li').forEach((option) => {
                    option.classList.remove('enable-hover-active');
                });
            }
        }
    </script>
</body>
</html>

The result is as below:

  • when "disabled", hover and click options enter image description here

  • when "enabled", hover and click options enter image description here

Upvotes: -1

Avatar
Avatar

Reputation: 15194

Use a second class that has only the hover assigned:

HTML

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

CSS

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

Now you can use Jquery to remove the class, for instance if the element has been clicked:

JQUERY

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

Hope this answer is helpful.

Upvotes: 20

Shobhit Sharma
Shobhit Sharma

Reputation: 634

I'd recommend to replace all :hover properties to :active when you detect that device supports touch. Just call this function when you do so as 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');
          }
        }
      }
    }
  }
}

Upvotes: 4

Caio Mar
Caio Mar

Reputation: 2624

I used the not() CSS operator and jQuery's addClass() function. Here is an example, when you click on a list item, it won't hover anymore:

For example:

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

Upvotes: 6

meo
meo

Reputation: 31259

Actually an other way to solve this could be, overwriting the CSS with insertRule.

It gives the ability to inject CSS rules to an existing/new stylesheet. In my concrete example it would look like this:

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

Demo with my 4 years old original example: http://jsfiddle.net/raPeX/21/

Upvotes: 1

Josh
Josh

Reputation: 11070

This is similar to aSeptik's answer, but what about this approach? Wrap the CSS code which you want to disable using JavaScript in <noscript> tags. That way if javaScript is off, the CSS :hover will be used, otherwise the JavaScript effect will be used.

Example:

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

Upvotes: 11

Paul D. Waite
Paul D. Waite

Reputation: 98906

There isn’t a pure JavaScript generic solution, I’m afraid. JavaScript isn’t able to turn off the CSS :hover state itself.

You could try the following alternative workaround though. If you don’t mind mucking about in your HTML and CSS a little bit, it saves you having to reset every CSS property manually 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');
)

Upvotes: 143

Stephen P
Stephen P

Reputation: 14830

You can manipulate the stylesheets and stylesheet rules themselves with 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);

Making the attributes !important and making this the very last CSS definition should override any previous definition, unless one is more specifically targeted. You may have to insert more rules in that case.

Upvotes: 12

Mottie
Mottie

Reputation: 86473

Try just setting the link color:

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

Edit: or better yet, use the CSS, as Christopher suggested

Upvotes: 1

Christopher Altman
Christopher Altman

Reputation: 4896

I would use CSS to prevent the :hover event from changing the appearance of the link.

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

This simple CSS means that the links will always be black and not underlined. I cannot tell from the question whether the change in the appearance is the only thing you want to control.

Upvotes: 3

Related Questions