0

I have created a class with an animation (changes the shape) for a button that will be triggered by a click. After the shapeshift, I wanted to have a hover effect which only changes the color. Each one works fine separately: .playBtn:hover and .pauseBtn:hover.

However, when I add both of them, it seems the animations disable the hover effects (the hover effect won't apply!). Does anyone have an idea why this happens?

Here is my code (main subject is CSS, but HTML and JS are also added just in case):

var bgMusic = document.getElementById("bgMusic"),
    musicBtn = document.getElementById("musicBtn"),
    music = false;

function toggleMusic() {
  if (music) {
    bgMusic.pause()
  } else {
    bgMusic.play();
  }
};

bgMusic.onplaying = function() {
  musicBtn.classList.remove("playBtn");
  musicBtn.classList.add("pauseBtn");
  music = true;
};

bgMusic.onpause = function() {
  musicBtn.classList.remove("pauseBtn");
  musicBtn.classList.add("playBtn");
  music = false;
};
#musicBtn {
  width: 0;
  height: 0;
  border-left: 16px solid grey;
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  margin-top: 3.5px;
  -webkit-transition-property: all;
  -moz-transition-property: all;
  -ms-transition-property: all;
  -o-transition-property: all;
  transition-property: all;
  -webkit-transition-duration: .4s;
  -moz-transition-duration: .4s;
  -ms-transition-duration: .4s;
  -o-transition-duration: .4s;
  transition-duration: .4s;
}

#musicBtn:hover {border-left: white 16px solid;}

.playBtn {animation: play-btn .6s ease forwards;}

@keyframes play-btn {
  from {
    transform: rotateZ(0);
    width: 5px;
    height: 15px;
    border-left: 5px solid white;
    border-top: 0 solid transparent;
    border-right: 5px solid white;
    border-bottom: 0 solid transparent;
  } to {
    transform: rotateZ(-360deg);
    width: 0;
    height: 0;
    border-left: 16px solid grey;
    border-top: 8px solid transparent;
    border-right: 0 solid transparent;
    border-bottom: 8px solid transparent;
  }
}

.playBtn:hover {border-left: 16px solid white;}  /*IT WON'T TAKE EFFECT!*/

.pauseBtn {animation: pause-btn .6s ease forwards;}

@keyframes pause-btn {
  from {
    transform: rotateZ(0deg);
    width: 0;
    height: 0;
    border-left: 16px solid grey;
    border-top: 8px solid transparent;
    border-right: 0 solid transparent;
    border-bottom: 8px solid transparent;
  } to {
    transform: rotateZ(360deg);
    width: 5px;
    height: 15px;
    border-left: 5px solid white;
    border-top: 0 solid transparent;
    border-right: 5px solid white;
    border-bottom: 0 solid transparent;
  }
}

.pauseBtn:hover {border-left: 5px solid grey; border-right: 5px solid grey;}  /*IT WON'T TAKE EFFECT!*/
<audio id="bgMusic" src="some music ...."></audio>
<div><div id="musicBtn" onclick="toggleMusic();"></div></div>
jsfiddle: https://jsfiddle.net/cf5abeoz/

1
  • Do you want the play button to turn white on hover? If so then it appears to be working for me. Check out this link here and let me know if it's any different than yours Commented Jun 24, 2020 at 0:17

2 Answers 2

1

When the animation-fill-mode property is set to forwards, the initial values will be overwritten with
"the computed values set by the last keyframe encountered during execution [of the animation]" (MDN docs).

I'm not entirely sure whether that means the :hover rules themselves also get overwritten, but either way, although the computed values are the same as the initial values, the :hover rules won't work anymore with the computed values. Also see this answer.

So your best option is probably to remove the forwards from your animation shorthand property.
Of course this creates other problems in your current code. In order to fix that, you need to set the same styles as at the end of the animation, to the basic selector for the .playBtn and .pauseBtn.
Finally, in order to prevent interference from the rules set for #musicBtn (in particular for the pause-button), you need to prepend #musicBtn to all your selectors.

So, for the play-button:  (and same for the pause-button)

.playBtn {animation: play-btn .6s ease forwards;}

becomes

#musicBtn.playBtn {
  width: 0;
  height: 0;
  border-left: 16px solid grey;
  border-top: 8px solid transparent;
  border-right: 0 solid transparent;
  border-bottom: 8px solid transparent;
  animation: play-btn .6s ease;
}

That's basically it. In the live snippet below I changed some other things as well, you can simply ignore those or see if you like them and apply them to your own code. They are not necessary for your code to work.

document.getElementById("musicBtn").onclick = function() {
  if (this.classList.contains("pause")) {
    this.classList.replace("pause","play");
  } else {
    this.classList.replace("play","pause");
  }
};
body {background:black;}

#musicBtn {-webkit-transition-duration:.4s; -moz-transition-duration:.4s; -ms-transition-duration:.4s; -o-transition-duration:.4s; transition-duration:.4s;}

#musicBtn.play {animation:play-btn .6s ease; width:0; height:0; border-left:16px solid grey; border-top:8px solid transparent; border-right:0 solid transparent; border-bottom:8px solid transparent;}
#musicBtn.play:hover {border-left:16px solid white;}
@keyframes play-btn {
  from {transform:rotateZ(0deg); width:5px; height:15px; border-left:5px solid white; border-top:0 solid transparent; border-right:5px solid white; border-bottom:0 solid transparent;}
  to {transform:rotateZ(-360deg); width:0; height:0; border-left:16px solid white; border-top:8px solid transparent; border-right:0 solid transparent; border-bottom:8px solid transparent;}
}

#musicBtn.pause {animation:pause-btn .6s ease; width:5px; height:15px; border-left:5px solid grey; border-top:0 solid transparent; border-right:5px solid grey; border-bottom:0 solid transparent;}
#musicBtn.pause:hover {border-left:5px solid white; border-right:5px solid white;}
@keyframes pause-btn {
  from {transform:rotateZ(0deg); width:0; height:0; border-left:16px solid white; border-top:8px solid transparent; border-right:0 solid transparent; border-bottom:8px solid transparent;}
  to {transform:rotateZ(360deg); width:5px; height:15px; border-left:5px solid white; border-top:0 solid transparent; border-right:5px solid white; border-bottom:0 solid transparent;}
}
<div class="play" id="musicBtn"></div>
jsfiddle: https://jsfiddle.net/njkqpz9L/1/

0

Remove the forwards fill-mode from the animation and the :hover styles will work correctly.

For more information on the different fill-modes see https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode.

Not the answer you're looking for? Browse other questions tagged or ask your own question.