Why Are CSS Animations and Transitions Blocked by JavaScript

Why are CSS animations and transitions blocked by JavaScript?

The selected answer is a bit out of date. As of today on OSX safari, firefox, and chrome all run css animations in separate thread from javascript.

CSS transitions blocked by JavaScript

Some people already mentioned that you should use timeouts. That's the appropriate approach, bc it'll give the browser time to "breathe" and render your progress bar mid-task.

You have to split your code up to work asynchronously. Say you currently have something like this:

function doAllTheWork() {
for(var i = 0; i < reallyBigNumberOfIterations; i++) {
processorIntensiveTask(i);
}
}

Then you need to turn it into something like this:

var i = 0;
function doSomeWork() {
var startTime = Date.now();
while(i < reallyBigNumberOfIterations && (Date.now() - startTime) < 30) {
processorIntensiveTask(i);
i++;
}

if(i < reallyBigNumberOfIterations) {
// Here you update the progress bar
incrementBar(i / reallyBigNumberOfIterations);

// Schedule a timeout to continue working on the heavy task
setTimeout(doSomeWork, 50);
}
else {
taskFinished();
}
}

function incrementBar(fraction) {
console.log(Math.round(fraction * 100) + ' percent done');
}

function taskFinished() { console.log('Done!'); }

doSomeWork();

Note the expression (Date.now() - startTime) < 30. That means the loop will get as much done as it can in the span of 30 milliseconds. You can make this number bigger, but anything over 100ms (essentially 10 frames-per-second) is going to start feeling sluggish from the user's point of view.

It may be true that the overall task is going to take somewhat longer using this approach as opposed to the synchronous version. However, from the user's experience, having an indication that something is happening is better than waiting indefinitely while nothing seems to be happening – even if the latter wait time is shorter.

Using CSS animation while javascript computes

CSS3 animations do not get blocked by Javascript unless there is some intense processing going on (in which case you could get stutters).

If you are triggering them during the load I could see them getting delayed until they get to that portion of the script.

One way around this is to setTimeouts at the very beginning of the script to trigger animation changes at certain times.

Another (perhaps better) option would be to use keyframes. Make sure to call this before the loading begins. http://dev.w3.org/csswg/css3-animations/#keyframes

Why blocking event loop does not block css animation?

This is because implementers are encouraged by the specs to not follow the specs...

alert() calls the pause algorithm, which should block the current task and cause the event loop to have nothing to do anymore than waiting for the "condition goal is met".

Though, this page also has a big warning paragraph stating,

Pausing is highly detrimental to the user experience, especially in scenarios where a single event loop is shared among multiple documents. User agents are encouraged to experiment with alternatives to pausing, such as spinning the event loop or even simply proceeding without any kind of suspended execution at all, insofar as it is possible to do so while preserving compatibility with existing content. This specification will happily change if a less-drastic alternative is discovered to be web-compatible.

So your UA certainly followed the advice to experiment with a spin-the-event-loop alternative, which allows for other tasks to still run, even though the one that called alert() has been paused.

CSS animation is blocked

besides the showed styles, the CSS on your page also contains

.headroom--unpinned {
display: none
}

wich you don't and can't transition, that interferes with your effect

CSS transition doesn't work with jQuery's .toggleClass()

transition doesn't work for display. try to change display:none and display:block to opacity:0 and opacity:1



Related Topics



Leave a reply



Submit