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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11131875/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 04:36:49  来源:igfitidea点击:

What is the cleanest way to disable CSS transition effects temporarily?

javascriptjquerycss

提问by Sam Saffron

I have a DOM element with some/all of the following effects applied:

我有一个应用了以下部分/所有效果的 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;
}

I am writing a jQuery plugin that is resizing this element, I need to disable these effects temporarily so I can resize it smoothly.

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

What is the most elegant way of disabling these effects temporarily (and then re-enabling them), given they may be applied from parents or may not be applied at all.

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

回答by Mark Amery

Short Answer

简答

Use this CSS:

使用这个 CSS:

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

Plus either this JS (without jQuery)...

加上这个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

Or this JS with jQuery...

或者这个带有 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

... or equivalent code using whatever other library or framework you're working with.

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

Explanation

解释

This is actually a fairly subtle problem.

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

First up, you probably want to create a 'notransition' class that you can apply to elements to set their *-transitionCSS attributes to none. For instance:

首先,您可能想要创建一个“notransition”类,您可以将其应用于元素以将其*-transitionCSS 属性设置为none. 例如:

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

(Minor aside - note the lack of an -ms-transitionin there. You don't need it. The first version of Internet Explorer to support transitions at allwas IE 10, which supported them unprefixed.)

(次要一边-注意缺少的-ms-transition。在那里,你不需要它的Internet Explorer的第一个版本,以支持过渡。在所有为IE 10,其支持他们前缀的。)

But that's just style, and is the easy bit. When you come to try and use this class, you'll run into a trap. The trap is that code like this won't work the way you might naively expect:

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

// 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 willbe animated, at least in all modern browsers I've tried. The problem is that the browser is caching 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.

天真地,您可能认为高度的变化不会被动画化,因为它发生在应用 'notransition' 类时。但实际上,它是动画的,至少在我尝试过的所有现代浏览器中都是如此。问题是浏览器会缓存它需要进行的样式更改,直到 JavaScript 完成执行,然后在一次重排中进行所有更改。因此,它会进行回流,其中是否启用转换没有净变化,但高度有净变化。因此,它动画高度变化。

You might think a reasonable and clean way to get around this would be to wrap the removal of the 'notransition' class in a 1ms timeout, like this:

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

// 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.

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

The only solution I've found to the problem is to forcea reflow of the element, flushing the CSS changes made to it, before removing the 'notransition' class. There are various ways to do this - see herefor some. The closest thing there is to a 'standard' way of doing this is to read the offsetHeightproperty of the element.

我发现这个问题的唯一解决方案是在删除“notransition”类之前强制重排元素,刷新对其所做的 CSS 更改。有多种方法可以做到这一点 - 请参阅此处了解一些信息。最接近“标准”的方法是读取offsetHeight元素的属性。

One solution that actually works, then, is

那么,一种实际有效的解决方案是

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

Here's a JS fiddle that illustrates the three possible approaches I've described here (both the one successful approach and the two unsuccessful ones): http://jsfiddle.net/2uVAA/131/

这是一个 JS 小提琴,它说明了我在这里描述的三种可能的方法(一种成功的方法和两种不成功的方法):http: //jsfiddle.net/2uVAA/131/

回答by DaneSoul

Add an additional CSS class that blocks the transition, and then remove it to return to the previous state. This make both CSS and JQuery code short, simple and well understandable.

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

CSS:

CSS:

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

!importantwas added to be sure that this rule will have more "weight", because ID is normally more specific than class.

!important添加是为了确保此规则将具有更多“权重”,因为 ID 通常比类更具体。

JQuery:

查询

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

回答by o.v.

I would advocate disabling animation as suggested by DaneSoul, but making the switch global:

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

.notransitioncan be then applied to the bodyelement, effectively overriding any transition animation on the page:

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

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

回答by Thomas Higginbotham

For a pure JS solution (no CSS classes), just set the transitionto 'none'. To restore the transition as specified in the CSS, set the transitionto an empty string.

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

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

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

If you're using vendor prefixes, you'll need to set those too.

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

elem.style.webkitTransition = 'none'

回答by Ali

You can disable animation, transition, trasforms for all of element in page with this css code

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

回答by Cyclonecode

I think you could create a separate css class that you can use in these cases:

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

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

Then in jQuery you would toggle the class like so:

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

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

回答by mrm

If you want a simple no-jquery solution to prevent all transitions:

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

  1. Add this CSS:
  1. 添加这个CSS:
body.no-transition * {
  transition: none !important;
}
  1. And then in your js:
  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)

回答by thomas

If you want to remove CSS transitions, transformations and animations from the current webpage you can just execute this little script I wrote (inside your browsers console):

如果您想从当前网页中删除 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);

It uses vanillaJS to load this css-file. Heres also a github repo in case you want to use this in the context of a scraper (Ruby-Selenium): remove-CSS-animations-repo

它使用 vanillaJS 来加载这个 css-file。如果您想在刮刀(Ruby-Selenium)的上下文中使用它,这里还有一个 github 存储库:remove-CSS-animations-repo

回答by Chris

does

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

in your js kill it?

在你的js里杀了吗?

obviously repeat for each.

显然每个重复。

回答by Moin Zaman

I'd have a class in your CSS like this:

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

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

and then in your jQuery:

然后在你的 jQuery 中:

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