Reuse CSS animation in reversed direction (by resetting the state?)
I've used two keyframe animations in CSS. One moves from left to right and the other one uses exact the same values - but reversed.
@keyframes moveLeft
{
from {transform: translate3d(50px, 0, 0);}
to {transform: translate3d(0px, 0, 0);}
}
@keyframes moveRight
{
from {transform: translate3d(0px, 0, 0);}
to {transform: translate3d(50px, 0, 0);}
}
However, I wonder whether it's possible to use one keyframe animation only. but as soon as I add animation-direction: reverse
, the animation does only play once. It probably saves the information that it has been used once before.
So: can I reset this information somehow? Or is there any possibility to use one animation twice in different directions? (without using JS)
http://jsfiddle.net/vrhfd66x/
No, there is no way to restart the animation using CSS alone. You'd have to use JavaScript to remove the animation from the element and then re-apply it to the element (after a delay) for it to restart.
The below is what the W3C's CSS3 Animation Spec says (in a different context, but the point should hold good for this case also):
Note also that changing the value of ‘animation-name’ does not necessarily restart an animation (e.g., if a list of animations are applied and one is removed from the list, only that animation will stop; The other animations will continue). In order to restart an animation, it must be removed then reapplied.
emphasis is mine
This CSS Tricks Article by Chris Coiyer also indicates the same and provides some JS solutions for restarting an animation. (Note: The article has a reference to Oli's dabblet which claims that altering properties like duration, iteration count makes it restart on Webkit but it seems to be outdated as they no longer work on Chrome).
Summary:
While you have already touched upon the following, I am going to re-iterate for completeness sake:
- Once an animation is applied on the element, it remains on the element until it is removed.
- UA does keep track of the animation being on the element and whether it has completed or not.
- When you apply the same animation on
:checked
(albeit with a different direction), the UA does nothing because the animation already exists on the element. - The switch of positions (instantaneous) while clicking the checkbox is because of the
transform
that is applied within the:checked
selector. The animation's presence makes no difference.
Solutions:
As you can see from the below snippet, achieving this with a single animation is pretty complex even when using JavaScript.
var input = document.getElementsByClassName("my-checkbox")[0];
input.addEventListener('click', function() {
if (this.checked) {
this.classList.remove('my-checkbox');
window.setTimeout(function() {
input.classList.add('anim');
input.classList.add('checked');
}, 10);
} else {
this.classList.remove('anim');
window.setTimeout(function() {
input.classList.remove('checked');
input.classList.add('my-checkbox');
}, 10);
}
});
input {
transform: translate3d(50px, 0, 0);
}
.my-checkbox {
animation: moveLeft 1s;
animation-direction: reverse;
}
.checked {
transform: translate3d(0px, 0, 0);
}
.anim{
animation: moveLeft 1s;
}
@keyframes moveLeft {
from {
transform: translate3d(50px, 0, 0);
}
to {
transform: translate3d(0px, 0, 0);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<input type="checkbox" class="my-checkbox">
So, the best option (if you want to stick to CSS animations) is to use two different animations.
Alternately, you could also have a look at Marcelo's comment. If the actual use-case is exactly what is provided in the fiddle then transition
would suffice and animation
isn't required. Transitions can work both in forward and reverse directions by nature and hence would be a safer bet.