Reputation: 77416
I want to skip a CSS transition under certain conditions. I'd prefer not to add special no-transition styles to my stylesheet, or duplicate my stylesheet's styles in my JavaScript. So far, the best solution I've found is
if (condition) {
$el.css({'-webkit-transition-duration': '0s'});
setTimeout(function() {
$el.css({'-webkit-transition-duration': ''});
}, 0);
};
$el.addClass('transitionClass');
(I've omitted the non-WebKit CSS for brevity. See it in action at http://jsfiddle.net/TrevorBurnham/zZBhx/.)
I don't like this because
$el
.Is there a better way?
Upvotes: 5
Views: 5820
Reputation: 674
Here are a couple of jquery plugins I wrote:
$.fn.redraw = function(){
var redraw = $(this).first()[0].offsetHeight || $('body')[0].offsetHeight; // forces a draw in the main window if the element is off screen
return this;
};
$.fn.cssNoTransition = function(){
$(this)
.css('transition', 'none')
.css.apply(this,arguments)
.redraw()
.css('transition', '');
return this;
};
Assuming the css says to transition height, use it like this:
this.$el.cssNoTransition({height: 0}).css({height: 200});
Upvotes: 1
Reputation: 1053
I know you said you didn't want to duplicate the style of the whole object in CSS, but have you thought about adding a special class just for the transition? Then you can define the element like this in the HTML:
<div id='#yourobject' class='transition'>
And when you don't want the transition, just do this (assuming jQuery):
$('#yourobject').removeClass('transition');
.... do some manipulation here
$('#yourobject').addClass('transition');
Upvotes: 4
Reputation: 8249
Here is a reliable method for skipping an element's CSS transition, the code comes from Mozilla's X-Tag Web Components library:
var prefix = (function () {
var styles = window.getComputedStyle(document.documentElement, ''),
pre = (Array.prototype.slice
.call(styles)
.join('')
.match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o'])
)[1];
return {
dom: pre == 'ms' ? pre.toUpperCase() : pre,
lowercase: pre,
css: '-' + pre + '-',
js: pre[0].toUpperCase() + pre.substr(1)
};
})();
var requestFrame = (function(){
var raf = window.requestAnimationFrame ||
window[prefix.lowercase + 'RequestAnimationFrame'] ||
function(fn){ return window.setTimeout(fn, 20); };
return function(fn){
return raf.call(window, fn);
};
})();
var skipTransition = function(element, fn, bind){
var prop = prefix.js + 'TransitionProperty';
element.style[prop] = element.style.transitionProperty = 'none';
var callback;
if (fn) callback = fn.call(bind);
requestFrame(function(){
requestFrame(function(){
element.style[prop] = element.style.transitionProperty = '';
if (callback) requestFrame(callback);
});
});
};
HOW TO USE IT - this snippet assumes you have set a transition on the foo
element's width and want to change it to 100px immediately without the element transitioning.
var foo = document.querySelector('#foo')
skipTransition(foo, function(){
foo.style.width = '100px';
});
LIVE EXAMPLE
Click each of the colored divs in the example - the red div has its width style set within the skipTransition function, thus preventing the transition and setting the style immediately. The blue div has its width set normally without skipTransition and the CSS transition effect occurs as normal: http://codepen.io/csuwldcat/pen/nFlse
Upvotes: 3
Reputation: 77416
Here's one approach: Clone the element, add the class to the clone, and replace the original element with the clone. Bam! No transition.
Demonstration: http://jsfiddle.net/TrevorBurnham/yXhBz/
This isn't ideal, though, because this breaks any stored references to the original element that you may have in your application. So I'd welcome an answer that operates synchronously on the existing element.
Upvotes: 2