Clean way to programmatically use CSS transitions from JS? Clean way to programmatically use CSS transitions from JS? javascript javascript

Clean way to programmatically use CSS transitions from JS?


There isn't a clean way at this moment (without using CSS Animations -- see the nearby answer by James Dinsdale for an example using CSS Animations). There is a spec bug 14617, which unfortunately wasn't acted upon since it was filed in 2011.

setTimeout does not work reliably in Firefox (this is by design).

I'm not sure about requestAnimationFrame -- an edit to the original question says it doesn't work reliably either, but I did not investigate. (Update: it looks like requestAnimationFrame is considered at least by one Firefox core developer to be the place where you can make more changes, not necessarily see the effect of the previous changes.)

Forcing reflow (e.g. by accessing offsetHeight) is a possible solution, but for transitions to work it should be enough to force restyle (i.e. getComputedStyle): https://timtaubert.de/blog/2012/09/css-transitions-for-dynamically-created-dom-elements/

window.getComputedStyle(elem).opacity;

Note that just running getComputedStyle(elem) is not enough, since it's computed lazily. I believe it doesn't matter which property you ask from the getComputedStyle, the restyle will still happen. Note that asking for geometry-related properties might cause a more expensive reflow.

More information on reflow/restyle/repaint: http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/


The situation has changed since 2013, so here's a new answer:

You could use Web Animations. They are implemented natively in Chrome 36 and Firefox 40 and there is a polyfill for all the other browsers.

Example code:

var player = snowFlake.animate([  {transform: 'translate(' + snowLeft + 'px, -100%)'},  {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}], 1500);// less than 1500ms later...changed my mindplayer.cancel();


You shouldn't need too much JavaScript to achieve what you want, just use CSS keyframes and animations for the same effect.

div {    opacity: 0;}div.fadeIn {    -webkit-animation: fadeIn 2s forwards;    animation: fadeIn 2s forwards;}@keyframes fadeIn {    0% {opacity: 0;}    100% {opacity: 1;}}@-webkit-keyframes fadeIn {    0% {opacity: 0;}    100% {opacity: 1;}}

As shown in this JsFiddle it works either from page load (with class already added) or when dynamically adding the class to trigger the animation.