Ответ 1
Короткий ответ
Используйте этот 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 *-transition
значение 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/