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

Posted

技术标签:

【中文标题】暂时禁用 CSS 过渡效果最干净的方法是啥?【英文标题】:What is the cleanest way to disable CSS transition effects temporarily?暂时禁用 CSS 过渡效果最干净的方法是什么? 【发布时间】:2012-06-23 07:36:10 【问题描述】:

我有一个应用了以下部分/全部效果的 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 插件来调整这个元素的大小,我需要暂时禁用这些效果,这样我才能顺利调整它的大小。

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

【问题讨论】:

这看起来很有希望:ricostacruz.com/jquery.transit。它是 MIT 许可的,所以你可以合并它,或者研究它,看看他是如何做到的。 所有答案添加 .notransition 类。反过来做会更合理,即用你的css定位#elem.yestransition并删除这个类。这消除了在你的 css 中有讨厌的*s。 【参考方案1】:

简答

使用这个 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

或者这个带有 jQ​​uery 的 JS...

$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;

(除了次要 - 请注意其中缺少 -ms-transition。您不需要它。第一个支持转换的 Internet Explorer 版本完全是IE 10,支持无前缀。)

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

// 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 完成执行,然后在一次重排中进行所有更改。因此,它会进行回流,对于是否启用过渡没有净变化,但对高度有净变化。因此,它会为高度变化设置动画。

您可能认为解决此问题的一种合理且干净的方法是将“notransition”类的删除包装在 1 毫秒超时内,如下所示:

// 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 在回流之前执行队列函数。

我发现该问题的唯一解决方案是强制重排元素,刷新对其所做的 CSS 更改,然后删除“notransition”类。有多种方法可以做到这一点 - 请参阅 here 了解一些。最接近“标准”的做法是读取元素的 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 fiddle,它说明了我在这里描述的三种可能的方法(一种成功的方法和两种不成功的方法): http://jsfiddle.net/2uVAA/131/

【讨论】:

优秀的答案。干得好,很感激,因为我遇到了同样的问题。如果我只想删除一种类型的过渡怎么办? 您的解决方案是正确的,但对于那些寻找更多背景信息的人:***.com/a/31862081/1026 除了 Minor 次要之外,IE10 是第一个带有无前缀转换的 IE stable 版本。预发布版本(不包括发布预览版)需要 -ms- 前缀进行转换,以及许多其他内容。我怀疑,这就是今天出现 -ms- 前缀的原因之一。当然,另一个更有可能的原因是我们都知道并喜欢供应商前缀的常见货物崇拜。 有趣的是,简单地检查元素的偏移高度就会触发回流。希望我一年前知道这一点,当时我正用同样的问题把头撞在墙上。这仍然被认为是处理这个问题的最理想方式吗? 在为没有 offsetHeight 属性的 SVG 元素设置动画时,回流技巧似乎不起作用; setTimout 有效。【参考方案2】:

我主张按照 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');

【讨论】:

实际上这是 imo 的完美选择。特别是 * 有很大帮助,确保不会触发任何子动画。谢谢,点赞。 这是您只想一次性完成所有工作的正确答案。例如,我想在移动设备上旋转时禁用过渡,这非常适合。 性能方面我不能指望这是一个好主意。 “哦,只需将其应用于页面上的所有内容,这会让事情变得更容易!” 应该同时选择“.notransition”和“.notransition *”才能完全生效。 我建议不要使用 !important ,除非你绝对必须这样做。它会在以后引起很多头痛。我已经在没有它的情况下尝试过,只要您遵循 CSS 的级联规则,它仍然可以正常工作。【参考方案3】:

添加一个额外的 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 比使用类更具体。

JQuery

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

【讨论】:

-1 因为这不足以解决我在 Chrome 或 Firefox 中的问题 - 如果我有添加类、进行更改和删除类的 Javascript,有时更改 仍然动画。我花了最后一两个小时详细研究了这个问题,稍后将发布一个答案,其中包含显示幼稚方法失败的情况的小提琴,以及一个巧妙的技巧,通过强制在进行更改和删除之间进行重排来修复这里的解决方案'notransition' 类。 我建议不要使用 !important ,除非你绝对必须这样做。它会在以后引起很多头痛。我已经在没有它的情况下尝试过,只要您遵循 CSS 的级联规则,它仍然可以正常工作。【参考方案4】:

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

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

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

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

elem.style.webkitTransition = 'none'

【讨论】:

【参考方案5】:

您可以使用此 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);

【讨论】:

首先这太棒了,谢谢!其次,还应该设置一些其他属性;见github.com/japgolly/test-state/blob/master/util/shared/src/test/… @Golly 其他属性可能会影响最终设计【参考方案6】:

我认为您可以创建一个单独的 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 块注入页面 你确定没有 !important CLASS 标尺会覆盖 ID 一吗?【参考方案7】:

如果您想要一个简单的非 jquery 解决方案来阻止所有转换:

    添加此 CSS:
body.no-transition * 
  transition: none !important;

    然后在你的 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)

【讨论】:

我也添加了一个animation: none !important;,但这可以解决问题。管理偏好运动减少非常方便。【参考方案8】:

这是对我来说很容易工作的解决方法。这不是问题的直接答案,但仍然可以帮助某人。

而不是创建应该取消转换的 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.classList.add("moveTransition")

后来在 setTimeout 中,我删除了它

element.classList.remove("moveTransition")

我无法在不同的浏览器中对其进行测试,但在 chrome 中它可以完美运行

【讨论】:

【参考方案9】:

如果您想从当前网页中删除 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 加载 this css-file。如果您想在刮板(Ruby-Selenium)的上下文中使用它,这里还有一个 github 存储库:remove-CSS-animations-repo

【讨论】:

【参考方案10】:

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

在你的js里杀了它?

显然对每个重复。

【讨论】:

那么你需要事后重置它,所以你需要存储它,这会导致相当多的样板【参考方案11】:

我会在你的 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

【讨论】:

你确定没有 !important CLASS 标尺会覆盖 ID 一吗? 是的,因为现在你的目标是#elem.no-transition,它比id更具体 @MoinZaman Erm,但是您还没有在 CSS 中定位 #elem.no-transition,您只是定位了 .no-transition。也许你打算在你的 CSS 中写 #elem.no-transition

以上是关于暂时禁用 CSS 过渡效果最干净的方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何禁用过渡或动画时间的悬停效果,然后在过渡或动画在 css 中完成后启用它?

我可以在构建元素时暂时关闭所有 CSS3 过渡/动画吗?

transition

更改 UINavigationController 过渡效果的正确方法是啥

CSS有个类似过渡的功能,是啥呢?

暂时绕过 CSS 过渡