Bug 107288 - Race condition when toggling classes disabling CSS transitions
Summary: Race condition when toggling classes disabling CSS transitions
Alias: None
Product: WebKit
Classification: Unclassified
Component: CSS (show other bugs)
Version: 528+ (Nightly build)
Hardware: Macintosh Intel OS X 10.8
: P2 Normal
Assignee: Nobody
URL: http://jsfiddle.net/m_gol/3hwjC/18/
Depends on:
Reported: 2013-01-18 08:49 PST by Michał Gołębiowski-Owczarek
Modified: 2013-01-18 09:14 PST (History)
1 user (show)

See Also:


Note You need to log in before you can comment on or make changes to this bug.
Description Michał Gołębiowski-Owczarek 2013-01-18 08:49:07 PST
Look at the linked jsFiddle. Because I want to transition the box moving upwards and it doesn't initially have 'top' set in CSS, I need to set it to window height minus box height while transitions are disabled. I am using a special class disabling transitions to set the initial value. However, WebKit seems to swap the following two commands in execution:
               div.style.top = (window.innerHeight - 50) + 'px';
               div.className = '';
so transitions are executed creating weird effects (just compare any WebKit browser to Firefox, Opera or IE10), even if I wrap lines 24-28 from linked jsFiddle in setTimeout (can be as long as you want). Wrapping the statement resetting className in setTimeout with even timeout equal to 0 solves the problem:
I can reproduce it in Chrome stable & Canary, Safari & WebKit nightly. Firefox, Opera & IE10 don't exhibit the issue.

Just a note: there is a separate issue in other browsers when you remove the 50ms callback wrapping the:
                div.style.top = '50px';
statement; non-WebKit browsers don't transition the box when it's moving upwards but I don't know if it's related to this bug.
Comment 1 Simon Fraser (smfr) 2013-01-18 08:59:14 PST
Style changes get batched by the browser (all browsers do this), so you can't do:

foo.style.bar = ....
foo.style.transition = 
foo.style.bar = ...

and expect that to work. The browser will only see the final styles.

There are a few workarounds. Use setTimeout(, 0) to do the final style change, or force layout by calling offsetWidth instead.
Comment 2 Michał Gołębiowski-Owczarek 2013-01-18 09:05:15 PST
The problem here is not only batching style changes because my example at:
uses setTimeout on the second change. The problem seems className changes batching and non-WebKit browsers don't do this, apparently, because this jsFiddle works correctly for them.
Comment 3 Michał Gołębiowski-Owczarek 2013-01-18 09:14:54 PST
Besides, look at:
There is no single place in this code where I'd do two or more style assignments without wrapping the second one in setTimeout with a large timeout and is still doesn't work in WebKit.

It seems className changes are batched together with style changes. Is it expected behavior? Other browsers don't do this (tested in Firefox, Opera & IE10).