How to smoothly revert CSS animation to its current state?

16,795

Solution 1

I just had the same problem and I solved it by not using animation and it works perfectly! Check out my solution: So I had this spatula that I had to move when hovered over only, and I wanted it to transition back smoothly, so this is what I did:

#Spatula:hover{
    animation-direction:alternate;
    transform: translate(1.2cm,1cm);
    transition: all 1.5s;
    -webkit-transition: all 1.5s;

}

#Spatula{
    -webkit-transition: all 1.5s;
    transition: all 1.5s;

}

Good luck!

Solution 2

You can't archive this effect only CSS3 way, but if you really need it, you could use jQuery + CSS3 Transitions. My solution (http://jsfiddle.net/sergdenisov/3jouzkxr/10/):

HTML:

<input type="checkbox" id="anim-input">
<label for="anim-input">Start / stop animation</label>
<div class="anim-div"></div>

CSS:

.anim-div { 
    margin-top: 50px;
    width: 50px;
    height: 10px;
    background: #000;
}

    .anim-div_active {
        -webkit-animation: moving 2s ease-in-out infinite alternate;
        animation: moving 2s ease-in-out infinite alternate;
    }

    .anim-div_return {
        -webkit-transition: -webkit-transform 0.5s ease-in-out;
        transition: transform 0.5s ease-in-out;
    }

@-webkit-keyframes moving {
    0% { -webkit-transform: translateX(0); }
    100% { -webkit-transform: translateX(300px); }
}

@keyframes moving {
    0% { transform: translateX(0); }
    100% { transform: translateX(300px); }
}

Javascript:

$('#anim-input').on('change', function() {
    var $animDiv = $('.anim-div');
    if (this.checked) {
        $animDiv.removeClass('anim-div_return')
                .addClass('anim-div_active');
        return;
    }

    var transformValue = $animDiv.css('webkitTransform') ||
                         $animDiv.css('transform');
    $animDiv.css({'webkitTransform': transformValue,
                  'transform': transformValue})
            .removeClass('anim-div_active');

    requestAnimationFrame(function() {
        $animDiv.addClass('anim-div_return')
                .css({'webkitTransform': 'translateX(0)',
                      'transform': 'translateX(0)'});
    });
});

P.S. Vendor prefixes are based on actual browsers list from http://caniuse.com.

Solution 3

Check out This StackOverflow question.

You aren't going to like this answer, but reality is that CSS3 animations aren't really useful to achieve this. To make this work you would need to replicate a lot of your CSS in your Javascript which kind of destroys the point (Like for example in this closely related answer Change speed of animation CSS3?). To really make it stop smoothly your best bet would be to write the animation on a platform like the Greensock animation library which provides all the tools you need to make it actually smoothly stop instead of suddenly stop.

There's also another answer below it that does make an effort at using CSS, you can look at that one.

Solution 4

There is also an alternate solution, it might not give you the desired effect of going back to it's original state, but since nobody mentioned it and this problem seems to have no solution, it's possible to pause the animation purely in css, locking it's state until it's started again

To pause the animation you need first to make the animation available even when the checkbox is not checked

And make use of the animation-play-state property

div { 
    margin-top: 50px;
    width: 50px; height: 10px;
    background: #000;
    animation: dance 2s infinite ease-in-out paused;
}

#anim:checked ~ div {
    animation-play-state: running;
}

@keyframes dance {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(300px); }
}
<input type="checkbox" id="anim">
<label for="anim">Start / stop animation</label>
    
<div></div>
Share:
16,795

Related videos on Youtube

Paweł
Author by

Paweł

Senior Product Designer at StackOverflow

Updated on September 03, 2022

Comments

  • Paweł
    Paweł over 1 year

    I've got not animated element as default. There's also a trigger that lets me turn on & off animation on that element. The animation itself is very simple: moves element from left to the right and back.

    When I stop animation, then my element obviously goes back to initial position. But it goes back suddenly, not smoothly. So it just changes its position from the one when I turned off animation to initial one. My question is: is there a way to stop it smoothly, so when I turn off the animation it goes back to initial position but smoothly/animating.

    Here's my element and animation: http://jsfiddle.net/2Lwftq6r/

    HTML:

    <input type="checkbox" id="anim">
    <label for="anim">Start / stop animation</label>
    <div></div>
    

    CSS:

    div { 
        margin-top: 50px;
        width: 50px; height: 10px;
        background: #000;
        transform: translateX(0);
    }
    
    #anim:checked ~ div {
        -webkit-animation: dance 2s infinite ease-in-out;
        -moz-animation: dance 2s infinite ease-in-out;
    }
    
    @-webkit-keyframes dance {
      0%, 100% { -webkit-transform: translateX(0); }
      50% { -webkit-transform: translateX(300px); }
    }
    @-moz-keyframes dance {
      0%, 100% { -moz-transform: translateX(0); }
      50% { -moz-transform: translateX(300px); }
    }
    
  • Rorschach120
    Rorschach120 almost 9 years
    On a related note, this is something that is being added to the angular animateCss service.
  • MrAn3
    MrAn3 over 5 years
    This is the simplest solution I've seen and it worked for me :)
  • tomexx
    tomexx over 3 years
    animation-direction:alternate; is not needed I guess
  • Manuel
    Manuel almost 3 years
    This is such a smart solution and works perfectly. It's not reverting the animation but definitely prevents the jump when not hovering the element anymore.