'Button hover does not work after I change button color using JS

I have a button that has a color change when hovering. And in Script the button color changes when a click event occurs. However, Hover works when the page is loaded but after the color changes, it doesn't work. The code is below:

var count = 1;

function setColor(btn, color) {
  var property = document.getElementById(btn);
  if (count == 0) {
    property.style.backgroundColor = "white";
    count = 1;
  } else {
    property.style.backgroundColor = color;
    count = 0;
  }
}
.button {
  background-color: #4caf50;
  /* Green */
  border: none;
  color: white;
  padding: 16px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  transition-duration: 0.4s;
  cursor: pointer;
}

.button1 {
  background-color: white;
  color: black;
  border: 2px solid #4caf50;
}

.button1:hover {
  background-color: red;
  color: black;
  border: 2px solid #4caf50;
}
<h2> Hoverable Buttons</h2>
<button id="buttonGreen" class="button button1" onclick="setColor('buttonGreen', '#122256')">
Green</button>

After I click the button event occurs and the color changes to dark blue and the hover do not work.



Solution 1:[1]

Inline styling (applied via style attribute) takes precedence over CSS applied styling (applied via class attribute).

Before click there was no background-color defined via style, after click there is which is overruling your CSS .button1:hover background-color. See documentation on CSS Specificity for more details on this topic.


To see the hover effect after clicking the button, try updating your .button1:hover to the following:

.button1:hover {
  background-color: red !important;
  color: black;
  border: 2px solid #4caf50;
}

Note the use of !important which instructs the browser to give precedence over the inline styling.

?? Using !important is generally not good practice therefore don't consider this to be a solution rather a topic to look into.

Solution 2:[2]

That occurs because you set background style white. Change this line in your condition. I would remove style elememnt. But you can set transparent background. What you are like!

if (count == 0) {
   // property.style.backgroundColor = "white";
   property.removeAttribute('style');
  ...

Working example

      var count = 1;
      function setColor(btn, color) {
        var property = document.getElementById(btn);
        if (count == 0) {          
          property.removeAttribute('style');
          count = 1;
        } else {
          
          property.style.backgroundColor = color;
          count = 0;
        }
      }
      .button {
        background-color: #4caf50; /* Green */
        border: none;
        color: white;
        padding: 16px 32px;
        text-align: center;
        text-decoration: none;
        display: inline-block;
        font-size: 16px;
        margin: 4px 2px;
        transition-duration: 0.4s;
        cursor: pointer;
      }

      .button1 {
        background-color: white;
        color: black;
        border: 2px solid #4caf50;
      }

      .button1:hover {
        background-color: red;
        color: black;
        border: 2px solid #4caf50;
      }
<html>
  <head>
    <style>

    </style>

    <script>

    </script>
  </head>

  <body>
    <h2>Hoverable Buttons</h2>
    <button
      id="buttonGreen"
      class="button button1"
      onclick="setColor('buttonGreen', '#122256')"
      ;
    >
      Green1
    </button>
  </body>
</html>

Note But better to use classes and then js toggle function.

Solution 3:[3]

You should probably avoid inline JS. Here's an example that uses a closure to prevent globals variables, and some modified CSS so you don't have to add styles directly on to the element. Think more of the button, and how it changes. You basically adding and removing colours, so make them the new CSS classes.

// Cache the button
const button = document.querySelector('button');

// Add an event handler to it. The handler is a function
// that returns another function which acts as the listener
// This way you don't need to create global variables.
// A function that's returned from another function, and carries
// with it the variables from its local lexical environment
// is called a closure.
button.addEventListener('click', setColor(), false);

function setColor(color) {
  
  // Initialise count
  let count = true;
  
  // Return the function to be used as the button
  // handler. Instead of updating the style directly
  // just simply add/remove classes to the element
  return function () {
    this.classList.remove('green');
    if (count) {
      this.classList.remove('blue');
      this.classList.add('white');
      this.textContent = 'White';
    } else {
      this.classList.add('blue');
      this.classList.remove('white');
      this.textContent = 'Blue';
    }

    // Change count to true if it's false, or
    // false if it's true
    count = !count;
  }

}
.button {
  border: 2px solid #4caf50;
  padding: 16px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  transition-duration: 0.4s;
  cursor: pointer;
}

.button:hover {
  background-color: red;
}

.white { background-color: white; }
.green { background-color: #4caf50; }
.blue { background-color: #122256; color: white; }
<h2>Hoverable Buttons</h2>
<button class="button green">Green</button>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Maik Lowrey
Solution 3 Andy