Коротка відповідь
Використовуйте цей 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/