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!