При наведении курсора на картинку, добавляется с помощью JS class .active
В стиле active указано, что картинка должно стать blur(10px) и transform: translateY(20px);
Анимация active выполняется отлично, но если мы захотим убрать active, чтобы вернуть обычное состояние, то картинка мигает перед концом анимации...
Как можно исправить?
Ответ
Сниппет для воспроизведения проблемы:
for (let img of document.querySelectorAll('.test')) {
img.addEventListener('mouseenter', function () { this.classList.add('active'); });
img.addEventListener('mouseleave', function () { this.classList.remove('active'); });
}
.test { transition: all 0.3s ease-out; }
.active { filter: blur(10px); transform: translateY(20px); }
Причина - ресурсоемкость размытия.
Соответственно, на 100% решить проблему невозможно. Но, можно применить CSS-вуду некоторые оптимизации, которые помогут в большинстве случаев.
upd.: После прочтения комментариев и проверки в Firefox (Win, Andr) и Opera (Win), делаю вывод что я ошибался относительно причин. Видимо, они все-таки в Chrome под винду и андроид.
Вариант решения:
for (let img of document.querySelectorAll('.test')) {
img.addEventListener('mouseenter', function () { this.classList.add('active'); });
img.addEventListener('mouseleave', function () { this.classList.remove('active'); });
}
.test {
transition: filter 0.3s steps(18),
transform 0.3s ease-out;
backface-visibility: hidden !important;
transform: translate3d(0, 0, 0) scale(1, 1);
}
.active {
filter: blur(10px);
transform: translate3d(0, 20px, 0) scale(1, 1);
}
Данное решение включает в себя (в порядке значимости):
ограничение числа кадров перехода, steps(18)
60кадров/с (лимит браузера) * 0,3с = 18
Это также делает временную функцию перехода линейной, что сильно ускоряет подсчеты (но это не просто аналог linear, а лучше).
отключение отрисовки оборотной стороны элемента через backface-visibility: hidden
Смысл очевиден: флип не выполняется => нет смысла рендерить оборотку.
исключение из пересчета transform трансформации по X и Z, а также масштабирования
Плюс, translate3d создает новый слой при рендеринге элемента - что, в свою очередь, должно вынудить браузер задействовать GPU не только при размытии.
Комментариев нет:
Отправить комментарий