Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toggling a CSS3 animation on click

What is the best way to alternate the direction of a CSS3 animation on click without javascript?

I've been exploring checkbox hacks lately and trying to figure out a way to have only one set of keyframes instead of two sets for one going forward and one to come back. Is this possible? Or is there a way to do it with one set?

For instance I have the following keyframes:

@keyframes moveIt {
  0%   { 
    transform: translateX(0);
    width: $size;
  }
  50%  {
    width: $size*1.2;
  }
  100% {
    transform: translateX(50px);
    width: $size;
  }
}
@keyframes moveItBack {
  100%   { 
    transform: translateX(0);
    width: $size;
  }
  50%  {
    width: $size*1.2;
  }
  0% {
    transform: translateX(50px);
    width: $size;
  }
}

Any way to reduce this to only the first set? Then when coming back start from 100% and go back to 0%?

Here is an example of what I am trying to accomplish this on.

like image 475
souporserious Avatar asked Apr 30 '14 16:04

souporserious


People also ask

How do I trigger an animation again in CSS?

The key to restarting a CSS animation is to set the animation-name of an animation to 'none' and then setting it back to the original animation. As you can see this requires two steps. One to switch it to a different animation and one to set it back.

Can you pause CSS animation?

The only way to truly pause an animation in CSS is to use the animation-play-state property with a paused value. In JavaScript, the property is “camelCased” as animationPlayState and set like this: element. style.


1 Answers

CSS is not really meant to do something like this but there are some work-arounds

Optimally we could do something like the following because it makes sense logically

.bubble {
  ...
  animation: moveIt .25s forwards ease-out;
}
input[type=checkbox]:checked ~ .bubble {
  animation: moveIt .25s backwards ease-out;
}

However, you cannot reset or change to a different animation using pure CSS[1]. This is because elements are only allowed to have one animation each. You can reset it in javascript by using setTimeout or cloning the element, but I assume you're trying to avoid that.

Thus, you're left with two options. The first is to ditch the change in size and just toggle the translateX like so:

.bubble {
  ...
  transition: all .25s ease-out;
}
input[type=checkbox]:checked ~ .bubble {
  transform: translateX(50px);
}

The other option to retain the change in size is to do something a bit more involved. You can essentially fake the change of size by using pseudo elements. By toggling the animation of both opposite from each other, you can make the whole element look like it pulses each time. Demo

.bubble {
  ...
  transition: all .25s ease-out;
}
.bubble:after, .bubble:before {
  content:''; 
  position:absolute;
  width:100%; height:100%;
  background:inherit;
  border-radius:inherit;
  animation:'';
}
.bubble:before { animation:size .25s ease-out; }
input[type=checkbox]:checked ~ .bubble:before { animation:''; }
input[type=checkbox]:checked ~ .bubble {
  transform: translateX(50px);
}
input[type=checkbox]:checked ~ .bubble:after {
  animation:size .25s ease-out;
}
@keyframes size {
  50% { transform:scale(1.2); }
}

I hope it makes sense!

[1]: As seen in the second option, it is possible, it just requires a state of removing the past animation. Sadly something like animation:''; animation:moveIt .25s backwards ease-out; does not reset it

like image 117
Zach Saucier Avatar answered Nov 12 '22 06:11

Zach Saucier