How to remove and add css animation property in single click with JavaScript

Viewed 1443

I have a problem regarding the css animation triggering with JavaScript. This is my code snippet:

const signInBtn = document.querySelector('#signin-btn');

function btnAnimation() {
  if (signInBtn.style.animation) {
    signInBtn.style.animation = '';
  } else {
    signInBtn.style.animation = 'btnAnimation 200ms linear';
  }
}

signInBtn.addEventListener('click', btnAnimation);
body {
  width: 100%;
  height: 100vh;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

button {
  border: 2px solid black;
  border-radius: 25px;
  width: 100px;
  height: 40px;
}

button:focus {
  outline: none;
}

.wrapper .signin {
  width: 200px;
  height: 200px;
  display: flex;
  justify-content: center;
  align-items: center;
}

@keyframes btnAnimation {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(.8);
  }
  100% {
    transform: scale(1);
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div class="wrapper">
    <div class="signin">
      <button id="signin-btn">SIGN IN</button>
    </div>
  </div>
</body>

</html>

So as you can see animation triggers every second click. I can't figure out how to add animation property after i removed it in "if" statement. I need this button to animate in every click. It is ok if you have a solution with jQuery but i would like to see pure JS solution. Thanks in advance.

1 Answers

The problem is that once you have the CSS style applied, it runs the animation once and that's it. So to trigger the animation again on a follow-up you need to reset the CSS for the button. Here I use setTimeout to reset the style after 220ms, which allows enough time for the css animation to complete before resetting the button style.

To target multiple buttons, you can use a common class between the elements. I chose btn-animation. Continuing on your style of code, I used document.querySelectorAll to get all of the elements by class name.

ES5

var nodes = document.querySelectorAll('.btn-animation');
for(var i = 0; i < nodes.length; i++) {
  nodes[i].addEventListener('click', function(event) {
    this.style.animation = 'btnAnimation 200ms linear';
    setTimeout(function(){
      event.target.style.animation = '';
    }, 220); // reset after delay -- allow enough time for animation to complete
  });
}
body {
  width: 100%;
  height: 100vh;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

button {
  border: 2px solid black;
  border-radius: 25px;
  width: 100px;
  height: 40px;
}

button:focus {
  outline: none;
}

.wrapper .signin {
  width: 200px;
  height: 200px;
  display: flex;
  justify-content: center;
  align-items: center;
}

@keyframes btnAnimation {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(.8);
  }
  100% {
    transform: scale(1);
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div class="wrapper">
    <div class="signin">
      <button id="signin-btn" class="btn-animation">SIGN IN</button>
      <button class="btn-animation">Option 1</button>
      <button class="btn-animation">Option 2</button>
      <button class="btn-animation">Option 3</button>
      <button class="btn-animation">Option 4</button>
      <button class="btn-animation">Option 5</button>
    </div>
  </div>
</body>

</html>

ES6

const nodes = document.querySelectorAll('.btn-animation');
for(let i = 0; i < nodes.length; i++) {
  nodes[i].addEventListener('click', (event) => {
    event.target.style.animation = 'btnAnimation 200ms linear';
    setTimeout(() => {
      event.target.style.animation = '';
    }, 220); // reset after delay -- allow enough time for animation to complete
  });
}
body {
  width: 100%;
  height: 100vh;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

button {
  border: 2px solid black;
  border-radius: 25px;
  width: 100px;
  height: 40px;
}

button:focus {
  outline: none;
}

.wrapper .signin {
  width: 200px;
  height: 200px;
  display: flex;
  justify-content: center;
  align-items: center;
}

@keyframes btnAnimation {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(.8);
  }
  100% {
    transform: scale(1);
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div class="wrapper">
    <div class="signin">
      <button id="signin-btn" class="btn-animation">SIGN IN</button>
      <button class="btn-animation">Option 1</button>
      <button class="btn-animation">Option 2</button>
      <button class="btn-animation">Option 3</button>
      <button class="btn-animation">Option 4</button>
      <button class="btn-animation">Option 5</button>
    </div>
  </div>
</body>

</html>

Related