CSSトランジション効果を一時的に無効にする最もクリーンな方法は何ですか?


209

次の効果の一部またはすべてが適用された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プラグインを作成しています。スムーズにサイズ変更できるように、これらの効果を一時的に無効にする必要があります。

親から適用されるか、まったく適用されない場合、これらの効果を一時的に無効にしてから再度有効にする最もエレガントな方法は何ですか。


1
これは有望に見えます:ricostacruz.com/jquery.transit。それはMITライセンスであるので、あなたはそれを組み込むか、彼がどのようにそれを行うかを調べるためにそれを研究することができます。
ロバートハーベイ

すべての答えはクラスを追加.notransitionます。それを逆に行う方がより合理的です。つまり#elem.yestransition、CSSをターゲットにして、このクラスを削除します。それは*あなたのCSSに厄介なs を持つことを取り除きます。
marcellothearcane

回答:


484

短い答え

この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

...または作業している他のライブラリまたはフレームワークを使用する同等のコード。

説明

これは実際にはかなり微妙な問題です。

最初に、要素に適用して*-transitionCSS属性をに設定できる「notransition」クラスを作成する必要があります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の実行が完了するまでブラウザーが行う必要があるスタイル変更をキャッシュし、その後、すべての変更を1回のリフローで行うことです。その結果、トランジションが有効であるかどうかの正味の変化はありませんが、高さの正味の変化があるリフローを実行します。その結果、高さの変化をアニメーション化します。

これを回避するための合理的でクリーンな方法は、次のように、「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はリフローの前にキューに入れられた関数を実行します。

この問題に対して私が見つけた唯一の解決策は、「notransition」クラスを削除する前に、要素に行われたCSSの変更をフラッシュして、要素を強制的にリフローすることです。これを行うにはさまざまな方法があります- いくつかはここを参照してください。これを行う「標準」の方法に最も近いのoffsetHeightは、要素のプロパティを読み取ることです。

実際に機能する1つの解決策は、

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

これが、ここで説明した3つの可能なアプローチ(1つの成功したアプローチと2つの失敗したアプローチの両方)を示すJSフィドルです。http//jsfiddle.net/2uVAA/131/


8
エクセレンテの答え。よくできました。同じ問題が発生したので、感謝しています。1つのタイプの遷移のみを削除したい場合はどうなりますか?
rafaelmorais 2014

2
あなたの解決策は正しいですが、より多くの背景情報を探している人のために:stackoverflow.com/a/31862081/1026
Nickolay

2
マイナーマイナーを除けば、IE10は、プレフィックスなしの遷移を備えて出荷された最初のIEの安定バージョンです。リリースプレビューを除くプレリリースバージョンでは、トランジションに-ms-プレフィックスが必要でしたが、他にも多くのものが必要でした。それが、今日、-ms-プレフィックスが現れる理由の1つだと私は思います。もちろん、もう1つの理由としては、ベンダープレフィックスについて私たち全員が知り、気に入っている通常のカーゴカルトがあります。
BoltClock

1
要素のオフセット高さをチェックするだけでリフローがトリガーされるのは興味深いことです。1年前にこれと同じ問題で頭を壁に打ちつけていたときに、これを知っていればよかったのに。これはまだこれを処理する最も理想的な方法と考えられていますか?
Brett84c

2
offsetHeight属性を持たないSVG要素をアニメーション化する場合、リフロートリックは機能しないようです。setTimoutが機能します。
piotr_cz 2017

19

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

2
実際、これは完璧なオプションです。特に*は非常に役立ち、サブアニメーションがトリガーされないようにします。ありがとう、賛成。
SchizoDuckie 2012

これは、一度にすべてを実行したい場合の正しい答えです。たとえば、モバイルで回転している間はトランジションを無効にしたいので、これはそのために最適です。
ベンラックマン、2013

私はこれをangularjsでやや複雑なシナリオで使用することになりましたが、神によって、これは私の頭を叩いた数日後にとても役に立ちました。
Aditya MP

2
パフォーマンスに関しては、これが良いアイデアであるとはまったく期待できません。「ああ、これをページのすべてに適用するだけで、作業が簡単になります!」
Lodewijk 14

1
完全に効果的にするには、おそらく「.notransition」と「.notransition *」の両方を選択する必要があります。
ネイサン

19

遷移をブロックする追加の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

5
-1これは、ChromeまたはFirefoxで問題を解決するには不十分でした。クラスを追加し、変更を加え、クラスを削除するJavaScriptを使用している場合、変更アニメーション化されることがあります。私は過去1〜2時間この問題を詳細に調査してきましたが、後で回答を投稿し、素朴なアプローチが失敗するケースを示し、変更を加えることと削除することの間のリフローを強制することによってソリューションをここで修正するきちんとしたハックを提供します「notransition」クラス。
Mark Amery 2013年

9

純粋なJSソリューション(CSSクラスなし)の場合は、をに設定transition'none'ます。CSSで指定されているとおりに遷移を復元するにはtransition、を空の文字列に設定します。

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

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

ベンダープレフィックスを使用している場合は、それらも設定する必要があります。

elem.style.webkitTransition = 'none'

8

この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);

1
まずこれは素晴らしいです、ありがとう!次に、設定する必要がある他のプロパティもあります。github.com/japgolly/test-state/blob/master/util/shared/src/test/…を
Golly

@Gollyこれらの他のプロパティは、最終的な設計に影響を与える可能性があります
jonperl 2018年

0

次の場合に使用できる別の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ブロックをページに挿入できます
Sam Saffron

3
重要なCLASSルーラーがなければID 1をオーバーライドしますか?
DaneSoul

0

すべての遷移を防ぐ単純な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)

-1

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-fileをロードします。これをスクレイパー(Ruby-Selenium)のコンテキストで使用する場合のgithubリポジトリもここにあります:remove-CSS-animations-repo


-3

する

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

あなたのjsでそれを殺しますか?

明らかにそれぞれについて繰り返します。


1
次に、事後にリセットする必要があるため、保管する必要があります。これにより、ボイラープレートがかなりの量になります
Sam Saffron

-4

私はあなたの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

1
重要なCLASSルーラーがなければID 1をオーバーライドしますか?
DaneSoul

1
はい。これは、idよりも具体的な#elem.no-transitionをターゲットにしているためです
Moin Zaman

3
@MoinZamanえーと、CSSでターゲットに設定しておらず、ターゲットに設定#elem.no-transitionしました.no-transition。たぶん、あなたは#elem.no-transitionあなたのCSSで書くつもりでしたか?
Mark Amery 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.