Quelle est la manière la plus propre à désactiver temporairement les effets de transition CSS?

J'ai un élément DOM avec certains / tous les effets suivants appliqués:

#elem { -webkit-transition: height 0.4s ease; -moz-transition: height 0.4s ease; -o-transition: height 0.4s ease; transition: height 0.4s ease; } 

J'écris un plugin jQuery qui redimensionne cet élément. Je dois désactiver temporairement ces effets afin que je puisse le redimensionner en douceur.

Quelle est la manière la plus élégante de désactiver ces effets temporairement (et de les réactiver à nouveau), étant donné qu'ils peuvent être appliqués par les parents ou ne peuvent être appliqués du tout.

Réponse courte

Utilisez ce CSS:

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

De plus, ce JS (avec jQuery) …

 $someElement.addClass('notransition'); // Disable transitions doWhateverCssChangesYouWant($someElement); $someElement[0].offsetHeight; // Trigger a reflow, flushing the CSS changes $someElement.removeClass('notransition'); // Re-enable transitions 

… ou un JavaScript équivalent utilisant des fonctions DOM brutes ou tout autre cadre avec lequel vous travaillez.

Explication

C'est en fait un problème assez subtil.

Tout d'abord, vous voulez probablement créer une classe de «non-transition» que vous pouvez appliquer aux éléments pour définir leurs *-transition CSS *-transition à none . Par exemple:

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

(À moindre à part – notez l'absence d'une -ms-transition-ms-transition dedans. Vous n'en avez pas besoin. La première version d'Internet Explorer pour supporter les transitions était IE 10, qui les soutenait non pré-réglé.)

Mais ce n'est que du style, et c'est un peu facile. Lorsque vous venez d'essayer d'utiliser cette classe, vous rencontrerez un piège. Le piège est que ce code comme celui-ci ne fonctionnera pas de la façon dont vous ne pouvez vous attendre à vous-même:

 // Don't do things this way! It doesn't work! $someElement.addClass('notransition') $someElement.css('height', '50px') // just an example; could be any CSS change $someElement.removeClass('notransition') 

Naïvement, vous pourriez penser que le changement de hauteur ne sera pas animé, car il se produit alors que la classe 'notransition' est appliquée. En réalité, il sera animé, du moins dans tous les navigateurs modernes que j'ai essayé. Le problème est que le navigateur met en cache les changements de style qu'il doit faire jusqu'à ce que le JavaScript ait fini d'être exécuté et que tous les changements se produisent en une seule refusion. Par conséquent, il ne reflète pas le changement net de la transition des transitions, mais il y a un changement net de hauteur. Par conséquent, il anime le changement de hauteur.

Vous pourriez penser qu'un moyen raisonnable et propre de contourner cela serait d'envelopper la suppression de la classe 'notransition' dans un délai d'expiration de 1 ms, comme ceci:

 // Don't do things this way! It STILL doesn't work! $someElement.addClass('notransition') $someElement.css('height', '50px') // just an example; could be any CSS change setTimeout(function () {$someElement.removeClass('notransition')}, 1); 

Mais cela ne fonctionne pas de manière fiable non plus. Je ne pouvais pas faire le code ci-dessus dans les navigateurs WebKit, mais sur Firefox (sur les machines lentes et rapides), vous allez parfois (apparemment au hasard) avoir le même comportement que d'utiliser l'approche naïve. Je suppose que la raison pour laquelle il est possible que l'exécution de JavaScript soit suffisamment lente pour que la fonction de temporisation soit en attente d'exécution au moment où le navigateur soit inactif et envisage de réfléchir de manière opportuniste, et si ce scénario se produit, Firefox exécute la fonction en attente avant la refusion.

La seule solution que j'ai trouvée sur le problème est de forcer une refusion de l'élément, de rincer les modifications CSS qui lui sont apportées, avant de supprimer la classe 'notransition'. Il existe plusieurs façons de le faire – voir ici pour certains. La chose la plus proche est celle d'une manière «standard» de faire ceci est de lire la propriété offsetHeight de l'élément.

Une solution qui fonctionne réellement, donc, est

 $someElement.addClass('notransition'); // Disable transitions doWhateverCssChangesYouWant($someElement); $someElement[0].offsetHeight; // Trigger a reflow, flushing the CSS changes $someElement.removeClass('notransition'); // Re-enable transitions 

Voici une violoncelle JS qui illustre les trois approches possibles que j'ai décrites ici (à la fois l'approche réussie et les deux non réussies): http://jsfiddle.net/2uVAA/35/

Ajoutez une classe CSS supplémentaire qui bloque la transition, puis retirez-la pour revenir à l'état précédent. Cela rend les codes CSS et JQuery courts, simples et compréhensibles.

CSS :

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

!important été ajouté pour être sûr que cette règle aura plus de «poids», car ID est normalement plus spécifique que la classe.

JQuery :

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

Je préconiserais la désactivation de l'animation comme suggéré par DaneSoul, mais rendant le commutateur global:

 /*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 peut alors être appliquée à l'élément du body , .notransition efficacement toute animation de transition sur la page:

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

Pour une solution JS pure (pas de classes CSS), configurez la transition vers 'none' . Pour restaurer la transition comme spécifié dans le CSS, définissez la transition vers une chaîne vide.

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

Si vous utilisez des préfixes de fournisseur, vous devrez également les configurer.

 elem.style.webkitTransition = 'none' 

Vous pouvez désactiver l'animation, la transition, les transformes pour tous les éléments dans la page avec ce 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); 

Je pense que vous pouvez créer une classe css distincte que vous pouvez utiliser dans ces cas:

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

Ensuite, en jQuery, vous basculeriez la classe comme suit:

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

Est-ce que

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

Dans votre js tuez-le?

Évidemment répète pour chacun.

J'aurais une classe dans votre CSS comme ceci:

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

Et ensuite dans votre jQuery:

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