CSS 3 Transitions with Opacity - Chrome and Firefox
I've been playing around with CSS3 transitions to fade in an overlay div when I came a cross an odd problem.
Basically I have a div element that has styles set on it's id - i.e. background-color: #000, opacity: 0, etc. As well as the browser-specific transition styles. By default the overlay element has a "hiddenElement" class on it, setting it's display to none.
When the overlay is to be displayed the hiddenElement class is removed, and another class is added "Initialised", this class sets the elements opacity to 0.6.
What I expected to happen was for the element to be animated in smoothly, which does happen in Opera, but in firefox and chrome it doesn't work exactly like that.
I've built an isolated case here: http://jsbin.com/obojet/27/.
As you can see when the "addClass('Initialised')" is wrapped in a setTimeout(), even with a timeout of 0ms in chrome, it animates correctly. Just doing addClass outside a timeout, w开发者_如何学Goont do the animation. In firefox, the timeout has to be longer - 50ms. In opera it just works.
It's probably down to the UI/Javascript contending for the single thread, but I was just curious if anyone else had experience similar issues.
I've had all sorts of issues with this. It's a really bad part of the CSS3 transitions specification because the spec says nothing about this type of behavior.
The predictable way to do this is:
- Set initial state of object.
- Set transition related CSS3 on the object.
- Object must not be
display: none
at this point. - Let browser return to event loop and repaint anything that needs repainting to establish pre-animation state.
- Then add a class to the object that sets the final state and triggers the animation.
- Return to browser event loop for the animation to take place.
The unpredictable way to do this is:
- Anything involving display: none in any of the states.
- Set intital state and CSS3 transition rules
- Set final state without letting browser go back to the event loop.
- Go back to event loop (often times the CSS3 transition will not go).
I see value in being able to change a whole bunch of properties at once programmatically without triggering the start of the CSS3 transition. But, it is not unusual that you want to establish the initial state with a bunch of code, programmatically set up the transition you want to have happen and then set the final state all in one piece of code. Today, you can't do that and get reliable behavior. You will have to insert some setTimeout calls in the middle. What would be nice would be to have a synchronous function call for setting the initial state that would say to the browser: OK, I'm doing setting the initial state of this object. Any changes I make from now on, I want you to include in the CSS3 transitions I have set. Then, you wouldn't need the extra setTimeout non-sense.
Your example shows this type of thing. You could make it work without the setTimeout by having your initial state be opacity: 0;
instead of display: none;
, though I realize that may not be what you want. Then, the initial state (without display: none) would be seen by the browser before you establish the final state and the transition should work.
精彩评论