Risposta breve
Usa questo CSS:
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
Inoltre o questo JS (senza jQuery) ...
someElement.classList.add('notransition');
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight;
someElement.classList.remove('notransition');
O questo JS con jQuery ...
$someElement.addClass('notransition');
doWhateverCssChangesYouWant($someElement);
$someElement[0].offsetHeight;
$someElement.removeClass('notransition');
... o codice equivalente utilizzando qualsiasi altra libreria o framework con cui stai lavorando.
Spiegazione
Questo è in realtà un problema abbastanza sottile.
Per prima cosa, probabilmente vorrai creare una classe "notransition" che puoi applicare agli elementi per impostare i loro *-transition
attributi CSS none
. Per esempio:
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
(Minore a parte - di notare che la mancanza di un -ms-transition
in là Non è necessario che la prima versione di Internet Explorer per le transizioni di supporto.. A tutti era IE 10, che ha sostenuto li senza prefisso).
Ma questo è solo stile ed è la parte facile. Quando verrai per provare a usare questa lezione, ti imbatterai in una trappola. La trappola è che un codice come questo non funzionerà nel modo in cui potresti ingenuamente aspettarti:
someElement.classList.add('notransition')
someElement.style.height = '50px'
someElement.classList.remove('notransition')
Ingenuamente, potresti pensare che il cambio di altezza non sarà animato, perché avviene mentre viene applicata la classe 'notransition'. In realtà, però, esso farà animato, almeno in tutti i browser moderni che ho provato. Il problema è che il browser memorizza nella cache le modifiche di stile che deve apportare fino al termine dell'esecuzione di JavaScript, quindi apporta tutte le modifiche in un unico reflow. Di conseguenza, esegue un reflow in cui non vi è alcuna modifica netta per stabilire se le transizioni sono abilitate o meno, ma c'è una modifica netta dell'altezza. Di conseguenza, anima il cambio di altezza.
Potresti pensare che un modo ragionevole e pulito per aggirare questo problema sarebbe racchiudere la rimozione della classe 'notransition' in un timeout di 1 ms, come questo:
someElement.classList.add('notransition')
someElement.style.height = '50px'
setTimeout(function () {someElement.classList.remove('notransition')}, 1);
ma neanche questo funziona in modo affidabile. Non sono stato in grado di eseguire la suddetta interruzione di codice nei browser WebKit, ma su Firefox (su macchine sia lente che veloci) a volte (apparentemente a caso) otterrai lo stesso comportamento dell'approccio ingenuo. Immagino che il motivo sia che è possibile che l'esecuzione di JavaScript sia abbastanza lenta da far sì che la funzione di timeout sia in attesa di essere eseguita nel momento in cui il browser è inattivo e altrimenti starebbe pensando di eseguire un reflow opportunistico e, se lo scenario si verifica Firefox esegue la funzione in coda prima del reflow.
L'unica soluzione che ho trovato al problema è forzare un reflow dell'elemento, svuotando le modifiche CSS apportate ad esso, prima di rimuovere la classe "notransition". Ci sono vari modi per farlo - vedi qui per alcuni. La cosa più vicina a un modo "standard" di farlo è leggere la offsetHeight
proprietà dell'elemento.
Una soluzione che funziona davvero, quindi, è
someElement.classList.add('notransition');
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight;
someElement.classList.remove('notransition');
Ecco un violino JS che illustra i tre possibili approcci che ho descritto qui (sia quello riuscito che i due non riusciti):
http://jsfiddle.net/2uVAA/131/