CSS animation triggered through JS only plays every other click



I want to make a simple JavaScript onclick animation. My problem is that when I click onto the button, the animation is executed, but when I click again onto the button, nothing happens. On the third clicks the animation plays again. I want to make that, the animation plays at the second click. Heres my code”

var anim = document.getElementById("anim");

anim.onclick = function highA() {

    var willCheck = document.getElementById("contactId");
    if (!willCheck.classList.contains("highAnim")) {
        willCheck.classList.add("highAnim");
    } else {
        willCheck.classList.remove("highAnim");
    }
}
#contactId { background: red;}

.highAnim {
    background-color: var(--white);
    animation-name: highcheck;
    animation-duration: 0.35s;
    animation-timing-function: ease-in-out;
}

@keyframes highcheck {
    0% {transform: rotate(0);}
    25% {transform: rotate(1deg);}
    50% {transform: rotate(2deg);}
    75% {transform: rotate(1deg);}
    100% {transform: rotate(0);}
}
<a onclick="anim()" id="anim">Click</a><br><br>
<div id="contactId">Some Text</div>

Answer

The issue is because the first click adds the class and triggers the animation, yet the second (and every even numbered click) after that removes the class so nothing happens.

To fix this you can use the animationend event to remove the class automatically after the animation has ended. That way when you next click again the class is added to the element once more and the animation plays. Try this:

var anim = document.getElementById("anim");
var willCheck = document.getElementById("contactId");

anim.addEventListener('click', () => {
  willCheck.classList.add("highAnim");
});

willCheck.addEventListener('animationend', () => {
  willCheck.classList.remove("highAnim");
});
#contactId { background: red; }

.highAnim {
  background-color: var(--white);
  animation-name: highcheck;
  animation-duration: 0.35s;
  animation-timing-function: ease-in-out;
}

@keyframes highcheck {
  0% { transform: rotate(0); }   
  50% { transform: rotate(2deg); }
  100% { transform: rotate(0); }
}
<a id="anim">Click</a><br><br>
<div id="contactId">Some Text</div>

Note that I removed the 25% and 75% items in the animation as it’s a linear motion from 0% to 50% and back again, so they are not needed. This also helps to make the animation smoother.



Source: stackoverflow