WebKit CSS Animation behavior weirdness
Okay, not weirdness. I guess more like (up until now) undocumented behavior. Due to a workaround that I needed to implement in order to properly clear out CSS properties when starting a new transition in my hacked-out S5 presentation, I filed Bug 23528: CSS transitions on opacity fail when used with visibility in certain circumstances.
When performing a transition, I had expected that a function like the following (simplified for demonstration) would work:
/**
* 1. take the element,
* 2. make it visible,
* 3. yet transparent,
* 4. then set the transition,
* 5. and then have it fade from opacity of 0 to 1 over one second.
*/
function fadeIn() {
// <span id="one" style="visibility: hidden;">testing</span>
var theOne = document.getElementById("one");
theOne.style.visibility = "visible";
theOne.style.opacity = 0;
theOne.style.WebkitTransition = "all 1s ease-in-out";
theOne.style.opacity = 1;
} Instead of fading in over one second, the span instantly appears, as if the last three lines of the function didn't even exist. This happens because CSS changes don't take effect when you assign new values. They queue up, taking effect once the JavaScript thread of execution ends. This makes sense for static changes, so that if you have a whole load of changes to apply to the DOM where many of the changes end up canceling out by the time the thread ends, the browser has no reason to apply each one of them to the DOM just in order to remove the change in the end. It also makes sense in a pure performance sense, since this keeps the JavaScript execution moving along at a nice, steady pace, rather than having to wait for the DOM to apply the change before moving on to the next step in the process.
Unfortunately for the code example above, it means that since the DOM node starts out completely opaque, the last three lines of the fadeIn function do effectively fall off and the span simply becomes visible. In order to get around this, the last couple of lines have to run on a different JavaScript "thread" so that it splits up the batched DOM changes into two parts and the node properly fades in:
function fadeIn() {
// <span id="one" style="visibility: hidden;">testing</span>
var theOne = document.getElementById("one");
theOne.style.visibility = "visible";
theOne.style.opacity = 0;
setTimeout(function() {
theOne.style.WebkitTransition = "all 1s ease-in-out";
theOne.style.opacity = 1;
}, 0);
}Labels: css, javascript, randomness, sample code, web standards, webkit
