我应用了一个具有此效果的 DOM 元素:
#elem {
transition: height 0.4s ease;
}
我正在编写一个 jQuery 插件来调整此元素的大小,我需要暂时禁用这些效果,以便我可以顺利调整它的大小。
暂时禁用这些效果(然后重新启用它们)的最优雅方法是什么,因为它们可能来自父母或可能根本不应用。
简答题
使用此 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
或者这个带有jQuery的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;
}
在继续之前,对CSS的一些小评论:
- 如今,您可能不想打扰供应商前缀的属性,例如
-webkit-transition
,或者可能有一个CSS预处理器将为您添加它们。当我在 2013 年首次发布此答案时,手动指定它们是大多数 Web 应用程序的正确做法,但截至 2023 年,根据 https://caniuse.com/mdn-css_properties_transition,世界上只有大约 0.4% 的用户仍在使用仅支持供应商前缀版本的浏览器transition
。 - 没有
-ms-transition
这样的事情.第一个支持转换的Internet Explorer版本是IE 10,它支持无前缀的转换。 - 此答案假设
!important
足以让此规则覆盖现有样式。但是,如果您已经在某些transition
规则中使用!important
,则可能不起作用。在这种情况下,您可能需要改为执行someElement.style.setProperty("transition", "none", "important")
来禁用转换(并自己弄清楚如何还原该更改)。
无论如何,当你尝试使用这个类时,你会遇到一个陷阱。陷阱是这样的代码不会像你天真期望的那样工作:
// 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"类的删除包装在 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);
但这也不能可靠地工作。我无法在 WebKit 浏览器中破坏上述代码,但在 Firefox 上(在慢速和快速机器上),您有时会(看似随机)获得与使用天真方法相同的行为。我想这样做的原因是 JavaScript 执行可能足够慢,以至于超时函数在浏览器空闲时等待执行,否则会考虑进行机会性回流,如果发生这种情况,Firefox 会在回流之前执行排队的函数。
我发现这个问题的唯一解决方案是强制重排元素,刷新对其所做的 CSS 更改,然后再删除"notransition"类。有多种方法可以做到这一点 - 请参阅此处了解一些方法。最接近"标准"方法的做法是读取元素的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/
我主张按照DaneSoul的建议禁用动画,但将切换设为全局:
/*kill the transitions on any descendant elements of .notransition*/
.notransition * {
transition: none !important;
}
然后,可以将.notransition
应用于 body
元素,从而有效地覆盖页面上的任何过渡动画:
$('body').toggleClass('notransition');
添加一个阻止转换的其他 CSS 类,然后将其删除以返回到以前的状态。这使得CSS和JQuery代码都简短,简单且易于理解。
CSS:
.notransition {
transition: none !important;
}
注意:添加!important
是为了确保此规则具有更高的优先级,因为使用 ID 比类更具体。
JQuery:
$('#elem').addClass('notransition'); // to remove transition
$('#elem').removeClass('notransition'); // to return to previouse transition
对于纯 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 = '* {' +
' transition-property: none !important;' +
' transform: none !important;' +
' animation: none !important;}';
document.getElementsByTagName('head')[0].appendChild(style);
您可以创建一个单独的 CSS 类,您可以在这些情况下使用:
.disable-transition {
transition: none;
}
然后在 jQuery 中,您将像这样切换类:
$('#<your-element>').addClass('disable-transition');
如果你想要一个简单的no-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)
这是对我来说很容易的解决方法。这不是对问题的直接回答,但仍然可以帮助某人。
而不是创建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 中它运行良好
如果你想从当前网页中删除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
$('#elem').css('-webkit-transition','none !important');
在你的JS中杀死它?
显然对每个重复。
我会在你的 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