Resposta curta
Use este CSS:
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
Além disso, este JS (sem 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
Ou esse JS com 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 código equivalente usando qualquer outra biblioteca ou estrutura com a qual você esteja trabalhando.
Explicação
Este é realmente um problema bastante sutil.
Primeiro, você provavelmente deseja criar uma classe 'notransition' que possa ser aplicada aos elementos para definir seus *-transition
atributos CSS none
. Por exemplo:
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
(Minor lado - nota a falta de um -ms-transition
. Lá você não precisa dele A primeira versão do Internet Explorer para transições de apoio. Em tudo foi IE 10, que os apoiaram unprefixed.)
Mas isso é apenas estilo e é fácil. Quando você tentar usar essa classe, encontrará uma armadilha. A armadilha é que um código como este não funcionará da maneira que você poderia esperar ingenuamente:
// 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')
Ingenuamente, você pode pensar que a mudança na altura não será animada, porque acontece enquanto a classe 'notransition' é aplicada. Na realidade, porém, será animado, pelo menos em todos os navegadores modernos que tentei. O problema é que o navegador está armazenando em cache as alterações de estilo que ele precisa fazer até que o JavaScript termine de executar e, em seguida, fazendo todas as alterações em um único reflow. Como resultado, ele faz um reflow em que não há alteração líquida para se as transições estão ou não ativadas, mas há uma alteração líquida na altura. Consequentemente, anima a mudança de altura.
Você pode pensar que uma maneira razoável e limpa de contornar isso seria envolver a remoção da classe 'notransition' em um tempo limite de 1 ms, assim:
// 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);
mas isso também não funciona de maneira confiável. Não consegui quebrar o código acima nos navegadores WebKit, mas no Firefox (em máquinas lentas e rápidas) às vezes você (aparentemente aleatoriamente) obtém o mesmo comportamento que usa a abordagem ingênua. Acho que o motivo disso é que é possível que a execução do JavaScript seja lenta o suficiente para que a função timeout esteja aguardando para ser executada no momento em que o navegador estiver ocioso e, caso contrário, estaria pensando em fazer um reflow oportunista e, se esse cenário acontecer, O Firefox executa a função na fila antes do reflow.
A única solução que encontrei para o problema é forçar um reflow do elemento, liberando as alterações de CSS feitas nele antes de remover a classe 'notransition'. Existem várias maneiras de fazer isso - veja aqui algumas. O mais próximo que existe de uma maneira "padrão" de fazer isso é ler a offsetHeight
propriedade do elemento.
Uma solução que realmente funciona, então, é
someElement.classList.add('notransition'); // Disable transitions
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight; // Trigger a reflow, flushing the CSS changes
someElement.classList.remove('notransition'); // Re-enable transitions
Aqui está um violino de JS que ilustra as três abordagens possíveis que descrevi aqui (a abordagem bem-sucedida e as duas sem êxito):
http://jsfiddle.net/2uVAA/131/