Mike C Mike C - 5 months ago 13
CSS Question

How to run the same animation when switching classes without JavaScript

I have an element which functions as a tri-state checkbox. I want to run an animation on that element whenever the state changes. Essentially, the element starts with no classes attached to indicate the first state. Then I add a class for one state, then remove that class and add a different one for the second state.

It works on the first click but the animation doesn't play on subsequent clicks. Here's what I have so far:



$('button').click(function() {
var $div = $('div');
if (!$div.hasClass('is-colored')) {
$div.addClass('green is-colored');
} else {
$div.toggleClass('green red');
}
});

@keyframes Animation {
from {
opacity: 0;
transform: scaleX(0) scaleY(0);
}
to {
opacity: 1;
transform: scaleX(1) scaleY(1);
}
}
.green {
background-color: #0F0;
-webkit-animation: Animation 0.25s linear forwards;
-moz-animation: Animation 0.25s linear forwards;
animation: Animation 0.25s linear forwards;
}

.red {
background-color: #F00;
/* I tried applying the animation on the second state but this isn't working */
-webkit-animation: Animation 0.25s linear forwards;
-moz-animation: Animation 0.25s linear forwards;
animation: Animation 0.25s linear forwards;
}
div {
width: 100px;
height: 100px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<button>Change Color</button>





I know it's possible to restart an animation with JavaScript and as of 3 years ago it didn't seem to be possible to do this without JavaScript.

In short, is it possible to perform the same animation on the same element multiple times using only CSS and toggling classes (i.e, no timeout required)?

Answer

What's happening is because the state never gets a reset so the animation doesn't kick in again. What you want to do is remove the color class as it resets, "wait" (0 seconds) then have the new class kick in for the animation.

The change is like this for green, see below for full changes:

$div.removeClass('green');

setTimeout(function() {
    $div.addClass('red');
}, 0);

Edit: To do this without javascript delay. The only way is to create another version of the animation so it constantly runs a different animation:

$('button').click(function() {
  var $div = $('div');
  if (!$div.hasClass('is-colored')) {
    $div.addClass('green is-colored');
  } else {
    $div.toggleClass('green red');
  }
});
@keyframes Animation {
  from {
    opacity: 0;
    transform: scaleX(0) scaleY(0);
  }
  to {
    opacity: 1;
    transform: scaleX(1) scaleY(1);
  }
}

@keyframes Animation2 {
  from {
    opacity: 0;
    transform: scaleX(0) scaleY(0);
  }
  to {
    opacity: 1;
    transform: scaleX(1) scaleY(1);
  }
}

.green {
  background-color: #0F0;
  -webkit-animation: Animation 0.25s linear forwards;
  -moz-animation: Animation 0.25s linear forwards;
  animation: Animation 0.25s linear forwards;
}

.red {
  background-color: #F00;
  /* I tried applying the animation on the second state but this isn't working */
  -webkit-animation: Animation2 0.25s linear forwards;
  -moz-animation: Animation2 0.25s linear forwards;
  animation: Animation2 0.25s linear forwards;
}
div {
  width: 100px;
  height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<button>Change Color</button>

Comments