Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bypassing transition and changing a property instantly

Tags:

I want to bypass CSS transition and change a property instantly.
I tried to set transition-duration to 0s before the change and then set transition-duration back to its original value:

$('div').css('width', '200px').delay(1000).queue(function() {     $(this).css({         transitionDuration: '0s',         msTransitionDuration: '0s',         mozTransitionDuration: '0s',         webkitTransitionDuration: '0s',         oTransitionDuration:'0s'     }).css('width', '10px').css({         transitionDuration: '2s',         msTransitionDuration: '2s',         mozTransitionDuration: '2s',         webkitTransitionDuration: '2s',         oTransitionDuration:'2s'     }) })​ 

Fiddle
This obviously doesn't work.

I understand that the spec does not define that behavior for this:

Since this specification does not define when computed values change, and thus what changes to computed values are considered simultaneous, authors should be aware that changing any of the transition properties a small amount of time after making a change that might transition can result in behavior that varies between implementations, since the changes might be considered simultaneous in some implementations but not others.

Is there an easy way to do this?

Note: The property I am changing is transform so .animate() would not be an option.

like image 917
TwiNight Avatar asked Dec 02 '12 14:12

TwiNight


People also ask

What is property transition?

transition properties allow elements to change values over a specified duration, animating the property changes, rather than having them occur immediately.

Which property specifies when the transition effect will start?

The transition effect will start when the specified CSS property (width) changes value.

Can you have multiple transition properties?

Transitioning two or more propertiesYou can transition two (or more) CSS properties by separating them with a comma in your transition or transition-property property. You can do the same with duration, timing-functions and delays as well. If the values are the same, you only need to specify one of them.

Why is transition-property not working?

When we want to use transition for display:none to display:block, transition properties do not work. The reason for this is, display:none property is used for removing block and display:block property is used for displaying block. A block cannot be partly displayed. Either it is available or unavailable.


1 Answers

Since nobody else is posting a valid answer, here goes:

$('div').css('width', '200px').delay(1000).queue(function() {     $(this).css({transition: '0s', width: '10px'}).delay(1).queue(function() {         $(this).css({transition:'2s'});     }); },1000)​; 

FIDDLE

Or if it's the other way:

$('div').css({     transition: '0s'   }).css('width', '200px').delay(1000).queue(function() {       $(this).css({width: '10px', transition: '2s'}); }); 

FIDDLE

jQuery should normalize vendor prefixes these days, so you don't have to type them all yourself.


The issue here is that jQuery attaches all the styles at once, only keeping the last styles, overwriting the previous styles of the same CSS property without ever doing a repaint of the DOM, and testing with native javascript seems to be doing the same thing, so it's probably the browser trying to avoid uneccessary reflows by adding a style just to have it changed in the next line of code, so doing:

$('div').css({     transition: '0s',     width: 200 }).css({     transition: '3s',     width: 10 }); 

won't work as only the last style is added.

This is where delay() comes into play, the OP's question was already using delay() so there was no reason not to use it, but removing delay() will of course cause the above issue, where the browser doesn't paint the first style, but only the last etc.

As delay() is really just a fancy timeout, it effectively defers the execution of the second setting of the styles, causing two browser repaints.

As this is most likely a browser issue, and not something we can change, deferring the setting of the second style is the only way to make this work, and using a delay will still work even if it's set to just 1 milliseconds, or one could defer the execution with a regular timeout, which is the usual way to defer execution of a script:

$('div').css({     transition: '0s',     width: 200 });  setTimeout(function() {     $('div').css({         transition: '3s',         width: 10     }); }); 

FIDDLE

The above will work just fine, as the timeout causes the first setting of the style to be painted by the browser, and defers the setting of the style inside the timeout to a later time, but as no time is set, it's executed as soon as the browser can (but still deferred until after the current script has completed), which for the human eye would seem like immediately, and that solves the issue.

like image 135
adeneo Avatar answered Oct 11 '22 14:10

adeneo