暂时禁用CSS过渡效果的最干净的方法是什么?

我有一个DOM元素的一些/所有以下效果应用:

#elem {
-webkit-transition: height 0.4s ease;
-moz-transition: height 0.4s ease;
-o-transition: height 0.4s ease;
transition: height 0.4s ease;
}

我正在写一个调整这个元素大小的jQuery插件,我需要暂时禁用这些效果,这样我就可以顺利地调整它的大小。

暂时禁用这些效果(然后重新启用它们)的最优雅的方法是什么?考虑到它们可能从父母那里应用,也可能根本不应用。

259355 次浏览

$('#elem').css('-webkit-transition','none !important');

在你的js杀死它?

显然,每一个都要重复。

我认为你可以创建一个单独的css类,你可以在这些情况下使用:

.disable-transition {
-webkit-transition: none;
-moz-transition: none;
-o-transition: color 0 ease-in;
-ms-transition: none;
transition: none;
}

然后在jQuery中,你可以这样切换类:

$('#<your-element>').addClass('disable-transition');

添加一个额外的CSS类来阻止转换,然后删除它以返回到以前的状态。这使得CSS和JQuery代码都简短、简单、易于理解。

CSS:

.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
}

注意:添加!important是为了确保该规则具有更高的优先级,因为使用id比使用class更具体。

JQuery:

$('#elem').addClass('notransition'); // to remove transition
$('#elem').removeClass('notransition'); // to return to previouse transition

我有一个类在你的CSS像这样:

.no-transition {
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
-ms-transition: none;
transition: none;
}

然后在jQuery中:

$('#elem').addClass('no-transition'); //will disable it
$('#elem').removeClass('no-transition'); //will enable it

我主张像DaneSoul建议的那样禁用动画,但要进行全局切换:

/*kill the transitions on any descendant elements of .notransition*/
.notransition * {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
}

然后,.notransition可以应用于body元素,有效地覆盖页面上的任何过渡动画:

$('body').toggleClass('notransition');

简短的回答

使用下面的CSS:

.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}

加上这个JS(没有jQuery)…

someElement.classList.add('notransition'); // Disable transitions
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight; // Trigger a reflow, flushing the CSS changes
someElement.classList.remove('notransition'); // Re-enable transitions

或者这个JS用jQuery…

$someElement.addClass('notransition'); // Disable transitions
doWhateverCssChangesYouWant($someElement);
$someElement[0].offsetHeight; // Trigger a reflow, flushing the CSS changes
$someElement.removeClass('notransition'); // Re-enable transitions

... 或者使用您正在使用的任何其他库或框架的等效代码。

解释

这实际上是一个相当微妙的问题。

首先,你可能想要创建一个“notransition”类,你可以将其应用于元素,将它们的*-transition CSS属性设置为none。例如:

.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}

(Minor aside -注意这里缺少-ms-transition。你不需要它。第一个支持转场 的IE是ie10,它支持无前缀转场。)

但这只是风格,而且是简单的部分。当您尝试使用这个类时,您将遇到一个陷阱。陷阱是这样的代码不会像你天真地期望的那样工作:

// Don't do things this way! It doesn't work!
someElement.classList.add('notransition')
someElement.style.height = '50px' // just an example; could be any CSS change
someElement.classList.remove('notransition')

你可能会天真地认为高度的变化不会被动画化,因为它发生在“notransition”类被应用的时候。实际上,它是动画的,至少在我尝试过的所有现代浏览器中是这样。问题是浏览器正在缓存它需要的样式更改,直到JavaScript完成执行,然后在一次reflow中完成所有更改。结果,它做了一个回流,无论是否启用过渡没有净变化,但有一个高度的净变化。因此,它动画高度变化。

你可能会想一个合理而干净的方法来解决这个问题,那就是在一个1ms的超时中包装'notransition'类的删除,就像这样:

// Don't do things this way! It STILL doesn't work!
someElement.classList.add('notransition')
someElement.style.height = '50px' // just an example; could be any CSS change
setTimeout(function () {someElement.classList.remove('notransition')}, 1);

但这也不可靠。我无法在WebKit浏览器中使上述代码中断,但在Firefox上(在慢速和快速的机器上),有时(似乎是随机的)会得到与使用幼稚方法相同的行为。我猜原因可能是JavaScript的执行速度足够慢,以至于超时函数在浏览器空闲时等待执行,否则就会考虑进行机会回流,如果发生这种情况,Firefox会在回流之前执行排队函数。

我发现这个问题的唯一解决方案是一个元素的回流,在删除'notransition'类之前刷新CSS对它的更改。有很多方法可以做到这一点——参见在这里。最接近“标准”的方法是读取元素的offsetHeight属性。

一个有效的解决方案是

someElement.classList.add('notransition'); // Disable transitions
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight; // Trigger a reflow, flushing the CSS changes
someElement.classList.remove('notransition'); // Re-enable transitions
下面是一个JS小提琴,它说明了我在这里描述的三种可能的方法(包括一个成功的方法和两个不成功的方法): http://jsfiddle.net/2uVAA/131/ < / p >

对于纯JS解决方案(没有CSS类),只需将transition设置为'none'。要恢复CSS中指定的转换,将transition设置为空字符串。

// Remove the transition
elem.style.transition = 'none';


// Restore the transition
elem.style.transition = '';

如果使用供应商前缀,也需要设置这些前缀。

elem.style.webkitTransition = 'none'

你可以禁用动画,过渡,转换的所有元素在页面的css代码

var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '* {' +
'/*CSS transitions*/' +
' -o-transition-property: none !important;' +
' -moz-transition-property: none !important;' +
' -ms-transition-property: none !important;' +
' -webkit-transition-property: none !important;' +
'  transition-property: none !important;' +
'/*CSS transforms*/' +
'  -o-transform: none !important;' +
' -moz-transform: none !important;' +
'   -ms-transform: none !important;' +
'  -webkit-transform: none !important;' +
'   transform: none !important;' +
'  /*CSS animations*/' +
'   -webkit-animation: none !important;' +
'   -moz-animation: none !important;' +
'   -o-animation: none !important;' +
'   -ms-animation: none !important;' +
'   animation: none !important;}';
document.getElementsByTagName('head')[0].appendChild(style);

如果你想从当前网页中删除CSS过渡,转换和动画,你可以执行我写的这个小脚本(在你的浏览器控制台):

let filePath = "https://dl.dropboxusercontent.com/s/ep1nzckmvgjq7jr/remove_transitions_from_page.css";
let html = `<link rel="stylesheet" type="text/css" href="${filePath}">`;
document.querySelector("html > head").insertAdjacentHTML("beforeend", html);

它使用vanillaJS加载这个css文件。这里还有一个github回购,以防你想在刮刀(Ruby-Selenium)的上下文中使用它:remove-CSS-animations-repo

如果你想要一个简单的非jquery解决方案来防止所有的过渡:

  1. 添加以下CSS:
body.no-transition * {
transition: none !important;
}
  1. 然后在js中:
document.body.classList.add("no-transition");


// do your work, and then either immediately remove the class:


document.body.classList.remove("no-transition");


// or, if browser rendering takes longer and you need to wait until a paint or two:


setTimeout(() => document.body.classList.remove("no-transition"), 1);


// (try changing 1 to a larger value if the transition is still applying)

这是一个对我来说很容易的解决方法。这不是对问题的直接回答,但仍然可能对某人有所帮助。

而不是创建应该取消转换的notransition

.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}

我创建了moveTransition

.moveTransition {
-webkit-transition: left 3s, top 3s;
-moz-transition: left 3s, top 3s;
-o-transition: left 3s, top 3s;
transition: left 3s, top 3s;
}

然后我用js把这个类添加到element中

element.classList.add("moveTransition")

之后在setTimeout中,我删除了它

element.classList.remove("moveTransition")

我无法在不同的浏览器中测试它,但在chrome中它工作得很好