Pull to refresh

Comments 27

Можете сделать ссылочку на jsfiddle? Скажу спасибо
А есть ли возможность в саму статью вставить блок CodePen? Я не знаю, как это делается, а в исходной статье он есть.
Ухты, webperf 101 в 2016 году на хабре, вот это да!
И еще забавно читать про «будущее за will-change». Это казалось будущим 2 года назад, но по итогам от этого свойства было скорее больше проблем, чем пользы, и оно все еще не поддерживается в IE/Edge, так что лучше по-стариночке юзать translate3d() там, где это необходимо.
Повторение — мать учения. И новичкам будет полезно)
Так и знал, что будет использовано какое-то магическое свойство, которое в половине браузеров не работает. Ну и за одно выдержки с MDN:

— Не применяйте will-change к большому числу элементов.
— Используйте умеренно.
— Не применяйте will-change к элементам для выполнения преждевременной оптимизации.
— Дайте ему достаточно времени, чтобы работать.
А насколько такой вариант кроссбраузный? Просто вариант с изменением ширины поддерживают все браузеры. Интересует практическое применение на мобильных устройствах
Вам не кажется, что что-то не так с технологией где нужны особые специальные ухищрения чтобы плавно подвинуть *один прямоугольник*?
Я лично считаю, что Москва не сразу строилась. И на то есть вполне объективные причины.
UFO landed and left these words here
На самом деле все что нужно сделать чтобы плавно подвинуть *один прямоугольник*:
.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 месяцев оно по прежнему будет выигрывать в производительности, потому что оптимизировать будут именно приведенный выше код.
Ок, давайте запретим CSS. Я создам петицию.
will-change. Оно указывает браузеру переместить элементы в отдельный слой так, чтобы он затем не проверял весь каркас на предмет сборки или отрисовки.


Нет, оно работает несколько иначе. Дело в том, что когда применяется анимация с transform, браузер копирует отрисованный элемент в виде текстуры и двигает уже непосредственно её. Однако, покуда он не знает, когда будут проводиться эти самые анимации, а держать и перерисовывать в памяти кучу подобных текстурок накладно, он это по-умолчанию делает в момент когда анимация началась, именно по этому он может (и обычно делает это) подвиснуть вначале анимации и сделать её не плавной. will-change говорит ему о том, что этот объект будет изменяться через animation и эту процедуру рендера в текстуру необходимо сделать заранее. Вот только после этого ему постоянно нужно проделывать достаточно много лишней работы (даже если вы просто будете водить курсором по пунктам меню), а так же будет жрать лишнюю память. Как следствие — это свойство лучше всего использовать ровно перед тем, как сама анимация будет совершена, например, навешивать это свойство при ховере, иначе пользователи будут вам благодарны, что у них браузер анимации воспроизводит плавно, но памяти стал есть в два раза больше.

P.S. На сколько я знаю, справедливо для webkit, gecko и как там у Edge движок называется, вероятно, весь процесс реализован иначе.
Ценный комментарий, спасибо!
это свойство лучше всего использовать ровно перед тем, как сама анимация будет совершена, например, навешивать это свойство при ховере

А как поступать, если мы открываем меню по нажатию горячих клавиш, на пример "m"? Добавлять свойство на keydown, а на keyup уже показывать? Но что если нужно показать непосредственно сразу при нажатии?

Спешу себя поправить по поводу «рендера в текстурку». Тут, возможно, я несколько погорячился, рендер в текстуру происходит не всегда, суть действительно в работе со слоями, но я боюсь даже представить насколько хитро работает внутри оптимизации. В текстуру он рендерит именно при афинных преобразованиях и прочих, производимых на видеокарте, не затрагивающих DOM (не приводящую к его пересчету). Это при медленных анимациях очень хорошо видно, покуда он применяет обычное сглаживание, характерное для текстур, а не pixel-perfect (т.е. черная линия в 1px будет выглядеть как серая в 2px).

Статья о том, как правильно пользоваться свойством will-change была как-то тут же на хабре, но, походу, канула в небытие, так что нашел похожую на dev.opera. Что касается горячих клавиш и, например, мобильных устройств — во втором случае все равно есть задержка в 40+ мс между событиями onTouch и onClick (не помню точно набор событий, но не суть), можно вешать на onTouch, а если пользователь не кликнул, а решил скроллить — отвешивать обратно. В случае горячих клавиш — вообще не использовать, оставлять это свойство только на тех элементах, которые с большей частью вероятности будут анимированы.
Для случая горячих клавиш можно просто сделать небольшой таймаут, скажем в 40мс. Глаз этого не заметит, а will-change успеет отработать.

А зачем тогда, собственно, will-change, если браузер все равно проведет подготовительные работы во время трансформации? Вся проблема will-change в том, что его сложно использовать. Мы все привыкли ко всяким там "непонятным" эвристикам и т.п., что браузер все за нас делает и т.п., и т.д. А тут появился will-changecontains ;)) и разработчики браузеров предложили нам все самим делать в помощь браузеру (увы, не во всех сценариях браузер может все верно оптимизировать и оптимизировать ли?..). kahi4, в целом, неплохо все объяснил. Дополню, что will-change нужен не только во время анимации, но и при любом ином изменении, а не только CSS transform. То, что делает это свойство, будет и без него проделано, но на эти подготовительные работы нужны ресурсы (время и мощности железа). При открытии меню, к примеру, мы хотим увидеть начало анимации сразу же после клика на кнопку и эти подготовительные работы отсрочат начало анимации на n миллисекунд, что будет замечено пользователем и испортит пользовательский опыт. Вот чтобы этого не происходило, посредством will-change можно подготовить элемент заранее. :)

Задержка до 100мс пользователями не воспринимается как задержка.

На подготовку слоев может уйти и больше. ;) Впрочем, я сего и не отрицал, хоть и не являюсь приверженцем данной теории...

Понятно, почему вынос меню вне .layout и применение transform увеличивают плавность, но совсем не понятно, почему добавление класса на время анимации делает это. Почему transition нет в .app-menu постоянно?

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, так типа анимация уже запущена просто на паузе)

Заголовок спойлера
зачем if-ом проверять наличие класса? classList.toggle(«класс») не… не слышал?..))
backface-visiblity: hidden уже давно ничего не триггерит в хроме (и скорее всегов фф). Год+ назад еще может работало, сейчас оно делает лишь то что должно, без 3д-акселерации.
Я один прочитал «анимируем» в заголовке как «онанируем»? :)
Only those users with full accounts are able to leave comments. Log in, please.