Комментарии 27
И еще забавно читать про «будущее за will-change». Это казалось будущим 2 года назад, но по итогам от этого свойства было скорее больше проблем, чем пользы, и оно все еще не поддерживается в IE/Edge, так что лучше по-стариночке юзать translate3d() там, где это необходимо.
— Не применяйте will-change к большому числу элементов.
— Используйте умеренно.
— Не применяйте will-change к элементам для выполнения преждевременной оптимизации.
— Дайте ему достаточно времени, чтобы работать.
.app-menu {
transform: translateX(-100%);
transition: transform 300ms linear;
}
Начиная от того что в Вашем примере не используются 3d трансформации, и заканчивая тем что Вы используете проценты.
Создайте страницу с большим количеством тегов и посмотрите на Ваш пример в дев тулс.
После этого примените 3d трансформацию но оставьте проценты
И после этого замените проценты на пиксели.
.app-menu {
transform: translate3d(-100px, 0, 0);
transition: transform 300ms linear;
width: 100px;
}
Этого уже достаточно и с производительностью все ok. А дичь, которую предлагают в конце статьи — это какие-то извращения с костылями. И не факт, что через n месяцев оно по прежнему будет выигрывать в производительности, потому что оптимизировать будут именно приведенный выше код.
will-change. Оно указывает браузеру переместить элементы в отдельный слой так, чтобы он затем не проверял весь каркас на предмет сборки или отрисовки.
Нет, оно работает несколько иначе. Дело в том, что когда применяется анимация с transform, браузер копирует отрисованный элемент в виде текстуры и двигает уже непосредственно её. Однако, покуда он не знает, когда будут проводиться эти самые анимации, а держать и перерисовывать в памяти кучу подобных текстурок накладно, он это по-умолчанию делает в момент когда анимация началась, именно по этому он может (и обычно делает это) подвиснуть вначале анимации и сделать её не плавной. will-change говорит ему о том, что этот объект будет изменяться через animation и эту процедуру рендера в текстуру необходимо сделать заранее. Вот только после этого ему постоянно нужно проделывать достаточно много лишней работы (даже если вы просто будете водить курсором по пунктам меню), а так же будет жрать лишнюю память. Как следствие — это свойство лучше всего использовать ровно перед тем, как сама анимация будет совершена, например, навешивать это свойство при ховере, иначе пользователи будут вам благодарны, что у них браузер анимации воспроизводит плавно, но памяти стал есть в два раза больше.
P.S. На сколько я знаю, справедливо для webkit, gecko и как там у Edge движок называется, вероятно, весь процесс реализован иначе.
это свойство лучше всего использовать ровно перед тем, как сама анимация будет совершена, например, навешивать это свойство при ховере
А как поступать, если мы открываем меню по нажатию горячих клавиш, на пример "m"? Добавлять свойство на keydown, а на keyup уже показывать? Но что если нужно показать непосредственно сразу при нажатии?
Статья о том, как правильно пользоваться свойством will-change была как-то тут же на хабре, но, походу, канула в небытие, так что нашел похожую на dev.opera. Что касается горячих клавиш и, например, мобильных устройств — во втором случае все равно есть задержка в 40+ мс между событиями onTouch и onClick (не помню точно набор событий, но не суть), можно вешать на onTouch, а если пользователь не кликнул, а решил скроллить — отвешивать обратно. В случае горячих клавиш — вообще не использовать, оставлять это свойство только на тех элементах, которые с большей частью вероятности будут анимированы.
А зачем тогда, собственно, will-change
, если браузер все равно проведет подготовительные работы во время трансформации? Вся проблема will-change
в том, что его сложно использовать. Мы все привыкли ко всяким там "непонятным" эвристикам и т.п., что браузер все за нас делает и т.п., и т.д. А тут появился will-change
(и contains
;)) и разработчики браузеров предложили нам все самим делать в помощь браузеру (увы, не во всех сценариях браузер может все верно оптимизировать и оптимизировать ли?..). kahi4, в целом, неплохо все объяснил. Дополню, что will-change
нужен не только во время анимации, но и при любом ином изменении, а не только CSS transform
. То, что делает это свойство, будет и без него проделано, но на эти подготовительные работы нужны ресурсы (время и мощности железа). При открытии меню, к примеру, мы хотим увидеть начало анимации сразу же после клика на кнопку и эти подготовительные работы отсрочат начало анимации на n миллисекунд, что будет замечено пользователем и испортит пользовательский опыт. Вот чтобы этого не происходило, посредством will-change
можно подготовить элемент заранее. :)
P.S. В коде в статье много семантических ошибок, советую смотреть код в оригинальной статье.
backface-visibility: hidden; (to the animation's parent element. The browser will think you're going to do some 3D transforms and takes measures to help keep things at a silky smooth 60fps.)
а это конкретно для @keyframes — animation-play-state: paused; (Set the animation's parent element's animation-play-state to paused and all its children to inherit. и когда нужно убираем паузу с помощью js, так типа анимация уже запущена просто на паузе)
Как по маслу, или анимируем со скоростью 60 FPS на CSS 3