CSS geçiş efektlerini geçici olarak devre dışı bırakmanın en temiz yolu nedir?


209

Aşağıdaki efektlerin bazıları / tümü uygulanmış bir DOM öğesi var:

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

Bu öğeyi yeniden boyutlandıran bir jQuery eklentisi yazıyorum, düzgün bir şekilde yeniden boyutlandırmak için bu efektleri geçici olarak devre dışı bırakmam gerekiyor.

Ebeveynlerden uygulanabileceği veya hiç uygulanmayabileceği göz önüne alındığında, bu etkileri geçici olarak devre dışı bırakmanın (ve daha sonra yeniden etkinleştirmenin) en zarif yolu nedir.


1
Bu umut verici görünüyor: ricostacruz.com/jquery.transit . MIT lisanslıdır, böylece onu dahil edebilir veya nasıl yaptığını görmek için inceleyebilirsiniz.
Robert Harvey

Tüm cevaplar bir sınıf ekler.notransition . Bunu başka bir şekilde yapmak daha makul olur, yani #elem.yestransitioncss'inizle hedefleyin ve bu sınıfı kaldırın. Bu *css içinde kötü s sahip kaldırır .
marcellothearcane

Yanıtlar:


484

Kısa cevap

Bu CSS'yi kullanın:

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

Artı ya bu JS (jQuery olmadan) ...

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

Veya jQuery ile bu JS ...

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

... veya üzerinde çalıştığınız diğer kitaplıkları veya çerçeveleri kullanarak eşdeğer bir kodu kullanabilirsiniz.

açıklama

Bu aslında oldukça ince bir sorundur.

İlk olarak, muhtemelen *-transitionCSS özniteliklerini ayarlamak için öğelere uygulayabileceğiniz bir 'notransition' sınıfı oluşturmak istersiniz none. Örneğin:

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

(Minör kenara - nota bir eksikliği -ms-transition. Orada Sen buna ihtiyacı yoktur destek geçişlerine Internet Explorer'ın ilk sürümü. Hiç bunları Öneksiz desteklenen IE 10 idi.)

Ama bu sadece stil ve kolay olanı. Bu sınıfı kullanmaya ve denemeye geldiğinizde bir tuzağa düşeceksiniz. Tuzak, bunun gibi kodun naif olarak beklediğiniz şekilde çalışmadığıdır:

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

Saf olarak, yükseklikteki değişikliğin canlandırılmayacağını düşünebilirsiniz, çünkü 'notransition' sınıfı uygulanırken olur. Gerçekte, en azından denediğim tüm modern tarayıcılarda animasyonlu olacak . Sorun, tarayıcının JavaScript'in çalışması bitene kadar yapması gereken stil değişikliklerini önbelleğe alması ve ardından tüm değişiklikleri tek bir yeniden akışta yapmasıdır. Sonuç olarak, geçişlerin etkin olup olmadığı konusunda net bir değişiklik olmadığı, ancak yükseklikte net bir değişiklik olduğu bir yeniden akış yapar. Sonuç olarak, yükseklik değişimini canlandırır.

Bu sorunun üstesinden gelmenin makul ve temiz bir yolunun 'notransition' sınıfının kaldırılmasını 1ms zaman aşımına uğramak olduğunu düşünebilirsiniz:

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

ancak bu da güvenilir bir şekilde çalışmaz. WebKit tarayıcılarında yukarıdaki kod kırmasını yapamadım, ancak Firefox'ta (hem yavaş hem de hızlı makinelerde) bazen (görünüşte rastgele) naif yaklaşımı kullanarak aynı davranışı elde edersiniz. Bunun nedeni, JavaScript yürütmesinin, zaman aşımı işlevinin tarayıcı boşta kaldığında ve aksi takdirde fırsatçı bir yeniden akış yapmayı düşünürken yürütmeyi bekleyecek kadar yavaş olabilmesinin mümkün olduğunu düşünüyorum ve bu senaryo gerçekleşirse, Firefox, yeniden akıştan önce kuyruğa alınan işlevi yürütür.

Soruna bulduğum tek çözüm , 'notransition' sınıfını kaldırmadan önce, üzerinde yapılan CSS değişikliklerini temizleyerek öğenin yeniden akışını zorlamak . Bunu yapmanın çeşitli yolları vardır - bazıları için buraya bakın . Bunu yapmanın 'standart' bir yoluna en yakın şey offsetHeight, elemanın özelliğini okumaktır .

Aslında işe yarayan bir çözüm,

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

Burada tarif ettiğim üç olası yaklaşımı gösteren bir JS kemanı (hem başarılı bir yaklaşım hem de başarısız olan iki yaklaşım): http://jsfiddle.net/2uVAA/131/


8
Excelente cevabı. İyi iş, ve aynı problemle geldiğimden beri takdir ediyorum. Yalnızca bir tür geçişi kaldırmak istersem ne olur?
rafaelmorais

2
Çözümünüz doğru, ancak daha fazla arka plan bilgisi arayanlar için: stackoverflow.com/a/31862081/1026
Nickolay

2
Küçük bir yana, IE10, IE'nin ön düzeltilmemiş geçişlerle birlikte gelen ilk kararlı sürümüdür. Yayın Önizleme sürümleri dışındaki yayın öncesi sürümler, geçişler için -ms- önekinin yanı sıra başka şeyler de gerektiriyordu. Şüpheliyim ki, bugün -ms- önekinin ortaya çıkmasının nedenlerinden biri budur. Diğer, çok daha muhtemel olan sebep, hepimizin satıcı önekleri hakkında bildiğimiz ve sevdiğimiz her zamanki kargo kültüdür.
BoltClock

1
Bir öğenin ofset yüksekliğini kontrol etmenin bir yeniden akış tetiklemesi ilginçtir. Bunu bir yıl önce aynı sorunla kafamı duvara vururken bilseydim. Bu hala bunu ele almanın en ideal yolu olarak mı görülüyor?
Brett84c

2
Yeniden akış hilesi, offsetHeight özniteliği olmayan SVG öğelerini canlandırırken çalışmıyor gibi görünüyor; setTimout çalışır.
piotr_cz

19

DaneSoul tarafından önerilen şekilde devre dışı bırakma animasyonunu savunurdum, ancak geçişi global hale getiririm:

/*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; 
} 

.notransitiondaha sonra bodyöğeye uygulanabilir ve sayfadaki herhangi bir geçiş animasyonunu etkin bir şekilde geçersiz kılar:

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

2
Aslında bu mükemmel bir seçenek imo. Özellikle *, alt animasyonların hiçbirinin tetiklenmediğinden emin olarak çok yardımcı olur. Teşekkürler, seçildi.
SchizoDuckie

Bu, hepsini aynı anda yapmak istediğiniz durumlar için doğru cevaptır. Örneğin, mobil cihazlarda dönerken geçişleri devre dışı bırakmak istiyorum ve bu bunun için mükemmel.
Ben Lachman

Bunu angularjs'de, biraz karmaşık bir senaryoda kullandım, ama tanrı tarafından bu gün kafamı vurduktan sonra çok yardımcı oldu.
Aditya MP

2
Performans açısından bunun iyi bir fikir olmasını bekleyemem. "Ah, bunu sayfadaki HER ŞEY'e uygulayın, bu işleri kolaylaştırır!"
Lodewijk

1
Tam olarak etkili olması için muhtemelen ".notransition" ve ".notransition *" öğelerini seçmeniz gerekir.
Nathan

19

Geçişi engelleyen ek bir CSS sınıfı ekleyin ve ardından önceki duruma dönmek için sınıfını kaldırın. Bu, hem CSS hem de JQuery kodunu kısa, basit ve anlaşılır hale getirir.

CSS :

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

!important kimliği normalde sınıftan daha spesifik olduğu için bu kuralın daha fazla "ağırlık" alacağından emin olmak için eklendi.

JQuery :

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

5
-1, çünkü bu sorunu Chrome veya Firefox'ta benim için çözmek için yeterli değildi - sınıfı ekleyen, değişiklikleri yapan ve sınıfı kaldıran Javascript'im varsa, bazen değişiklikler hala canlandırılır. Son bir ya da iki saati bu sorunu ayrıntılı olarak inceleyerek geçirdim ve daha sonra naif yaklaşımın başarısız olduğu durumları gösteren kemanların yanı sıra, değişiklikleri yapmak ve kaldırmak arasında bir yeniden akışı zorlayarak çözümü burada sabitleyen düzgün bir kesmek ile bir cevap yayınlayacağım. 'notransition' sınıfı.
Mark Amery

9

Saf bir JS çözümü için (CSS sınıfı yok), sadece transitiondeğerini ayarlayın 'none'. Geçişi CSS'de belirtildiği gibi geri yüklemek için, transitionboş bir dizeye ayarlayın.

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

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

Satıcı önekleri kullanıyorsanız, bunları da ayarlamanız gerekir.

elem.style.webkitTransition = 'none'

8

Bu css kodu ile sayfadaki tüm öğelerin animasyon, geçiş ve şekil formlarını devre dışı bırakabilirsiniz

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
Öncelikle bu harika, teşekkürler! İkincisi, ayarlanması gereken başka özellikler de vardır; bkz. github.com/japgolly/test-state/blob/master/util/shared/src/test/…
Golly

@Golly Bu diğer özellikler son tasarımı etkileyebilir
jonperl

0

Bu durumlarda kullanabileceğiniz ayrı bir css sınıfı oluşturabileceğinizi düşünüyorum:

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

Daha sonra jQuery'de sınıfı şu şekilde değiştirirsiniz:

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

evet bence bu en iyi yaklaşım, aslında eklenti bu css bloğunu sayfaya enjekte edebilir
Sam Saffron

3
Önemli CLASS cetveli olmadan ID ID'yi geçersiz kılacağınızdan emin misiniz?
DaneSoul

0

Tüm geçişleri önlemek için basit bir jquery çözümü istemiyorsanız:

  1. Bu CSS'yi ekle:
body.no-transition * {
  transition: none !important;
}
  1. Ve sonra senin 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 geçişlerini, dönüşümlerini ve animasyonlarını geçerli web sayfasından kaldırmak istiyorsanız, yazdığım bu küçük komut dosyasını (tarayıcı konsolunuzun içinde) yürütebilirsiniz:

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

Bu css dosyasını yüklemek için vanillaJS kullanır . Heres ayrıca bir kazıyıcı (Ruby-Selenium) bağlamında kullanmak istediğinizde bir github repo: remove-CSS-animations-repo


-3

yapar

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

senin js öldürmek?

açıkçası her biri için tekrarlayın.


1
o zaman gerçeği sonra sıfırlamanız gerekir, bu yüzden saklamanız gerekir, bu adil bir kazan plakası yol açacaktır
Sam Saffron

-4

CSS'nizde şöyle bir sınıf olurdu:

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

ve sonra jQuery'nizde:

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

1
Önemli CLASS cetveli olmadan ID ID'yi geçersiz kılacağınızdan emin misiniz?
DaneSoul

1
Evet, çünkü şimdi sadece id'den daha spesifik olan # elem.no-transition hedefliyorsunuz
Moin Zaman

3
@MoinZaman Erm ama henüz hedeflenen #elem.no-transitionCSS'nizde, sadece hedeflediğiniz .no-transition. Belki de CSS'nize yazmak #elem.no-transitionistediniz?
Mark Amery
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.