71

Given the following CSS3 animation....

<style type="text/css" media="screen">

.drop_box {
  -webkit-animation-name: drop;
  -webkit-animation-duration: 2s;
  -webkit-animation-iteration-count: 1;
}

@-webkit-keyframes drop {

  from {
    -webkit-transform: translateY(0px);
  }

  to {
    -webkit-transform: translateY(100px);
  }

}
</style>

<div class="drop_box">  
    Hello world
</div>

The Hello World text animates as expected dropping down 100px. However, at the end of the animation it jumps back to its original position.

Clearly this makes sense in CSSland. The animation has been applied and is no longer acting on the element so the original styles take effect. It seems slightly odd to me though - surely if one is animating an element into place then one would expect that placing to persist?

Is there any way of making the end position 'sticky' without having to resort to Javascript to tag a classname or style onto the element at the end of the animation to fix its altered properties? I know that transitions persist, but for the animation I have in question (the example is for demonstration purposes only) transitions don't give the level of control needed. Without this, it seems that complex animations are only of use for circular processes where the element ends up back in its original state.

Community
  • 1
  • 1
Govan
  • 913
  • 1
  • 6
  • 7

5 Answers5

147

You can use -webkit-animation-fill-mode to persist the end state (or even extend the start state backwards). It was added to WebKit a while ago, and shipped in iOS 4 and Safari 5.

-webkit-animation-fill-mode: forwards;
JP Silvashy
  • 46,977
  • 48
  • 149
  • 227
dino
  • 1,479
  • 2
  • 8
  • 2
33

If you define the end state in the class then it should do what you want in the example:

.drop_box {
    -webkit-transform: translateY(100px);
    -webkit-animation-name: drop;
    -webkit-animation-duration: 2s;
    -webkit-animation-iteration-count: 1;
}

But if your animation is event driven anyway you will probably end up having to use a bit of JavaScript. The easiest way is to make the adding of the class with the end state in it be what triggers the animation to start.

--edit

See dino's answer for information on the animation-fill-mode property added in the April 2012 WD.

Community
  • 1
  • 1
robertc
  • 74,533
  • 18
  • 193
  • 177
  • Was just coming back to post that :-) Yes, it seems that one *has* to use javascript to achieve this. Not a massive issue, but still a bit of a let down in what is meant to be an animation module. – Govan Jul 18 '10 at 13:02
  • @Govan There were a couple of quite long discussions on the W3C www-style list back in March about what the standard should end up looking like (http://lists.w3.org/Archives/Public/www-style/2010Mar/0469.html) and whether to have separate animations and transitions at all (http://lists.w3.org/Archives/Public/www-style/2010Mar/0230.html). It's entirely possible that, if the standard goes forward, there'll be some better way of specifying a static end state. – robertc Jul 18 '10 at 13:40
  • It seems like JS is not maybe necessary in all cases. As suggest by Robertc, it's possible to actually define the end state in the class. For example if you animate top, set top in the class to whatever you want it to be at the end, and then set your values for the animation. This at least works on Safari. So that – user18490 Aug 13 '14 at 11:45
1

Just to add to the great answers here, you could use a javascript framework such as jQuery Transit that handles the CSS3 transitions for you.

Depending on how many transitions/effects you will be doing, this may be a better solution in keeping your code clean rather than keeping up with a large CSS file that has all of your effects in it.

This is a very simple one-liner that accomplishes what you want:

Javascript:

$(".drop_box").transition({y: "+=100px"}, 2000);

JS Fiddle Demo

Gaff
  • 5,507
  • 3
  • 38
  • 49
0

Yet another way to do this, just for kicks,

    <style type="text/css" media="screen">

.drop_box {
   position:absolute;
   top:100px;
  -webkit-animation-name: drop;
  -webkit-animation-duration: 2s;
  -webkit-animation-iteration-count: 1;
}

@-webkit-keyframes drop {

  from {
  -webkit-transform: translateY(-100px);
  }

  to {
  -webkit-transform: translateY(0px);
  }

}
</style>

<div class="drop_box">  
Hello world
</div>
apaul
  • 16,092
  • 8
  • 47
  • 82
0

I think what you might be looking for is:

0% {
  -webkit-transform: translateY(0px);
}

100% {
  -webkit-transform: translateY(100px);
}

This should leave it in the right place.

JP Silvashy
  • 46,977
  • 48
  • 149
  • 227
Michael Mullany
  • 30,283
  • 6
  • 81
  • 105