2

So a situation I have quite often is to immediatly trigger a CSS transition after I created an element. Usually, I do this by adding a class.

Edit: code example now inline:

var ele = document.createElement("div");
ele.id = "target";
ele.innerHTML = "I'm the target element";
document.body.appendChild(ele);
ele.clientHeight; // <-- leave this out, and it will not animate!
document.getElementById("target").className = "foo";
.foo {
    background-color: #cc0;
    transition:all 3s ease;
}

But using this kind of (simplified) code does not work:

myEle.className = "baseClass";
myEle.className += " transitionClass";

Immediatly adding a class does not trigger anything, bc when the JS thread returns, the element is already in the transitioned state. So there is more that must be done. I have found out the following ways to achieve this:

1) requestAnimationFrame

myEle.className = "baseClass";
requestAnimationFrame(function () { myEle.className += " transitionClass"; });

Unfortunately, this is not very reliable, in some browsers it works, but very often it does not, esp. in Firefox.

2) setTimeout

myEle.className = "baseClass";
setTimeout(function () { myEle.className += " transitionClass"; }, 50);

Now, this works in general, but I found that I have to use values quite large to make it work reliably (again, esp. in Firefox) - about 50ms or even more. So this adds quite a bit of lag.

3) forcing reflow

myEle.className = "baseClass";
myEle.clientHeight;
myEle.className += " transitionClass";

Another way I have found lately is simply to force a reflow of the element by asking for some properties like clientHeight. So far, this works well, but as I see it, while it does not seem to add a lag, it might add some computional overhead, since the reflow is not only triggered once (by adding the class), but twice instead.

Right now, I would tend to use method 3) but the questions are:

  • does this really work reliably across the board?
  • Is this actually the fastest method? and
  • does the CPU overhead matter more than the lag introduced with setTimeout?

Of course you should restrict reflow to the element you animate, and not ask for body width, I guess that will even be more expensive. Since most of my animated elements have position: absolute anyways, I also guess the overhead is not too much to actually matter, but I am still not sure whats the best way, so any hints and insights are greatly appreciated!

frontend_dev
  • 1,693
  • 14
  • 28
  • 1
    *"Immediatly adding a class does not trigger anything, bc when the JS thread returns, the element is already in the transitioned state."* No, that's not the case: http://jsfiddle.net/ca3ee5y8/ Note how the transition continues well past the point the JavaScript thread has yielded back to the browser. Perhaps you could demonstrate an example of the problem you're trying to solve with an [MCVE](/help/mcve) using Stack Snippets (the `<>` toolbar button). – T.J. Crowder Nov 14 '15 at 15:18
  • Yes, if the element already existed, but I create and insert it dynamically. So try this:http://jsfiddle.net/ca3ee5y8/2/ vs this: http://jsfiddle.net/ca3ee5y8/1/ – frontend_dev Nov 14 '15 at 15:33
  • *"Edit: to make it more clear, look at this example"* Your question must not rely on off-site content. To be more clear, put the necessary information clearly in the question, not hidden behind a link. – T.J. Crowder Nov 14 '15 at 15:41
  • That's very interesting about Firefox needing a >0 timeout. For me, it starts working at 3 (Firefox 42, Linux): http://jsfiddle.net/ca3ee5y8/4/ In any case, could be a good question, put the [MCVE](/help/mcve) in the question, highlight that it's about an element you just added. Good luck, – T.J. Crowder Nov 14 '15 at 15:49
  • [Possible duplicate of this question](http://stackoverflow.com/a/24195559/157247), where the accepted answer says your reflow is the way to go. – T.J. Crowder Nov 14 '15 at 15:52
  • Triggering a reflow might be problematic if you're starting multiple animations at once. – Bergi Nov 14 '15 at 16:37
  • The answer in the possible duplicate also states: "Most of the time accessing the reflow-causing properties in between DOM modifications can cause serious slowdown." So while it seems to be more reliable, my question aims at the drawbacks of each solution, and if using timeout might be more efficient in terms of CPU usage. On the other hand, having to add a timeout this large also does not seem optimal to me. And yes, this varies wildly on FF, even seems to be affected by the OS you are running, and also seems to depend on the specific usecase. – frontend_dev Nov 14 '15 at 16:44
  • On the the other hand, is the reflow impact that huge on elements that are not part of the main layout, i.e. by using position: absolute or fixed? And I also take care of my transitions being calculated on the GPU entirely, by only using transforms and / or opacity. – frontend_dev Nov 14 '15 at 16:45

0 Answers0