我有一个DOM元素与此效果应用:

#elem {
  transition: height 0.4s ease;
}

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

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


当前回答

我有一个类在你的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 * { 
  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;
}

在继续之前,有一些关于CSS的次要说明:

These days you may not want to bother with the vendor-prefixed properties like -webkit-transition, or may have a CSS preprocessor that will add them for you. Specifying them manually was the right thing to do for most webapps when I first posted this answer in 2013, but as of 2023, per https://caniuse.com/mdn-css_properties_transition, only about 0.4% of users in the world are still using a browser that supports only a vendor-prefixed version of transition. There's no such thing as -ms-transition. The first version of Internet Explorer to support transitions at all was IE 10, which supported them unprefixed. This answer assumes that !important is enough to let this rule override your existing styles. But if you're already using !important on some of your transition rules, that might not work. In that case, you might need to instead do someElement.style.setProperty("transition", "none", "important") to disable the transitions (and figure out yourself how to revert that change).

无论如何,当您尝试使用这个类时,您将遇到一个陷阱。陷阱是这样的代码不会像你天真地期望的那样工作:

// 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')

Naively, you might think that the change in height won't be animated, because it happens while the 'notransition' class is applied. In reality, though, it will be animated, at least in all modern browsers I've tried. The problem is that the browser is buffering the styling changes that it needs to make until the JavaScript has finished executing, and then making all the changes in a single "reflow". As a result, it does a reflow where there is no net change to whether or not transitions are enabled, but there is a net change to the height. Consequently, it animates the height change.

你可能会想一个合理而干净的方法来解决这个问题,那就是在一个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);

but this doesn't reliably work either. I wasn't able to make the above code break in WebKit browsers, but on Firefox (on both slow and fast machines) you'll sometimes (seemingly at random) get the same behaviour as using the naive approach. I guess the reason for this is that it's possible for the JavaScript execution to be slow enough that the timeout function is waiting to execute by the time the browser is idle and would otherwise be thinking about doing an opportunistic reflow, and if that scenario happens, Firefox executes the queued function before the reflow.

我发现这个问题的唯一解决方案是强制元素的回流,在删除“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

下面是我在这里描述的三种可能的方法(包括一种成功的方法和两种不成功的方法): http://jsfiddle.net/2uVAA/131/

我有一个类在你的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

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

而不是创建一个应该取消转换的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中它工作得很好

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

CSS:

.notransition {
  transition: none !important;
}

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

JQuery:

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