0

So, I can create an location animation of an element by doing something like this:

Widget.style.left = Dest.x;
Widget.style["-webkit-transition"] = "left 0.3s ease-in-out";

This works fantastically so long as the widget already exists. The problem is when I create a new widget, and want to start it off screen, there doesn't seem to be an obvious and elegant way to set the start location.

Predictably, if I try this:

Widget.style.left = Src.x;
Widget.style.left = Dest.x;
Widget.style["-webkit-transition"] = "left 0.3s ease-in-out";

The source location is ignored seems to have no effect.

Arelius
  • 1,216
  • 8
  • 15

1 Answers1

1

This is both a problem and a feature with CSS transitions. The browser only sees the "state" of an object that it can use for a transition when your javascript is done executing so only when that happens can the "initial" state of an object be set and likewise, only then can the final state of an object for transitions be seen by the browser. That means that:

Widget.style.left = Src.x;
Widget.style.left = Dest.x;

won't do anything. If the object is brand new, the only state the browser will see (for the purposes of transitions is Dest.x and that will be treated as the initial state (thus no transition).

The only way I've found around it is to let my javascript finish and use a timer to kick off the transition:

// create Widget
Widget.style.left = Src.x;
Widget.style["-webkit-transition"] = "left 0.3s ease-in-out";
// user a timer to get the current location marked as the starting location
// and then set the new location
setTimeout(function() {
    Widget.style.left = Dest.x;  // trigger transition from Src.x to Dest.x
}, 0);

I say this is both a feature and a problem because it has its benefits along with its problems. If you move an object around a couple times in the middle of one piece of javascript, the object won't transition between all those intermediate locations, it will only transition to the final location. But, it does create problems like what you're running into.

Edit: This post Cannot dynamically set initial element translation before transition in same call stack suggests that there is a work-around that forces a browser layout by accessing any one of a number of specific properties after you set the start position before you set the final position. I have not tried it myself.

This work-around seems to work here in Chrome: http://jsfiddle.net/jfriend00/VqTHV/

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I figured that may be the solution, I guess I was just hoping that there existed something like widget.style.commit() or something of the like. – Arelius Mar 17 '12 at 20:46
  • I found a potential work-around and added it to the end of my answer. – jfriend00 Mar 17 '12 at 21:04
  • Hmm, I haven't actually tried to make a minimal test case, but within my application, it seems that this is not working, It now seems to move to the first location, and then once the timeout expires it moves to the second without animation. Only *if* it's a new item, but it animates properly if it's been around for a while. – Arelius Mar 17 '12 at 21:06
  • Hah! My other problem (In the comment above) was due to forcing a layout between setting the new location, and setting the webkit-transition, due to calling one of those calls mentioned in your edit! thanks! – Arelius Mar 17 '12 at 21:12
  • I added a jsFiddle that shows the work-around working of just accesssing clientHeight on the object. This seems to force a layout of the object and thus establishes it's initial position. Note, you will want the -webkit-transiton values already set at the initial position too. – jfriend00 Mar 17 '12 at 21:18