CSS Animations and the UI Thread

A quick demonstration of unexpected behavior when setting transitions and properties via JS.

by nate

HTML

<ul>
    <li></li>
</ul>

<ul>
    <li></li>
</ul>

CSS

ul {
    border: 10px solid blue;
    height: 200px;
    margin: 0 0 1em;
    position: relative;
    width: 300px;
}

li {
    background: yellow;
    height: 200px;
    left: 0;
    position: absolute;
    top: 0;
    width: 300px;
}

JavaScript

var ele1 = document.getElementsByTagName( 'li' )[0],
    ele2 = document.getElementsByTagName( 'li' )[1],
    transition = 'all 0.5s',
    start = function() {
        
        // Based purely on order of operations, we would espect both yellow
        // squares NOT to animate, but to immediately jump to 300px to the right
        
        // Instead, we see example one animate into position (not desired)
        ele1.style.left = '300px';
        ele1.style.WebkitTransition = transition;
        ele1.style.MozTransition = transition;
        
        // Example two, which uses a setTimeout to add the transition property
        // after the UI thread is complete, behaves as expected
        ele2.style.left = '300px';
        setTimeout( (function() {
            ele2.WebkitTransition = transition;
            ele2.style.MozTransition = transition;
        }), 0 );
    
    };

start();