Короткий ответ
Используйте этот 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
Или этот JS с JQuery ...
$someElement.addClass('notransition'); // Disable transitions
doWhateverCssChangesYouWant($someElement);
$someElement[0].offsetHeight; // Trigger a reflow, flushing the CSS changes
$someElement.removeClass('notransition'); // Re-enable transitions
... или эквивалентный код с использованием любой другой библиотеки или фреймворка, с которым вы работаете.
объяснение
Это на самом деле довольно тонкая проблема.
Во-первых, вы, вероятно, захотите создать класс «notransition», который вы можете применить к элементам для установки их *-transition
атрибутов CSS 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, а затем вносит все изменения в одном перекомпоновании. В результате он выполняет перекомпоновку, где нет чистого изменения того, разрешены ли переходы, но есть чистое изменение высоты. Следовательно, он оживляет изменение высоты.
Вы могли бы подумать, что разумным и чистым способом обойти это было бы завершение удаления класса «notransition» за 1 мс, например:
// 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 выполняет функцию из очереди до перекомпоновки.
Единственное решение, которое я нашел для этой проблемы, состоит в том, чтобы принудительно перекомпоновать элемент, сбрасывая изменения CSS, внесенные в него, перед удалением класса notransition. Существуют различные способы сделать это - посмотрите здесь для некоторых. Наиболее близким к «стандартному» способу сделать это является чтение offsetHeight
свойства элемента.
Одно из решений, которое действительно работает,
someElement.classList.add('notransition'); // Disable transitions
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight; // Trigger a reflow, flushing the CSS changes
someElement.classList.remove('notransition'); // Re-enable transitions
Вот сценарий JS, который иллюстрирует три возможных подхода, которые я описал здесь (как один успешный, так и два неудачных):
http://jsfiddle.net/2uVAA/131/