Для перемещения элемента по экрану есть два основных способа:
- CSS 2D-преобразования и
translate()
; position:absolute
и изменениеtop/left
.
Крис Койер недавно писал, почему лучше и логичнее использовать translate
(это быстрее, и свойство position
имеет большее отношение к вёрстке, а не к визуальным эффектам и анимации, в отличие от translate
).
Я хочу расширить его ответ и привести несколько хороших примеров. Я записал скринкаст, в котором помощью Chrome DevTools timline рассматриваю различия между этими подходами с точки зрения производительности, особенностей рендеринга и композитинга на GPU.
Если вам нужна сокращённая текстовая версия — продолжайте читать.
Начнём с примеров, которые приводил Крис:
Это вполне корректные примеры, но они настолько просты, что оба варианта выглядят отлично. Мы возьмем что-то более сложное, чтобы как следует нагрузить браузер, и тогда разница станет гораздо заметнее (спасибо joshua за иконку макбука)
Вот так гораздо лучше. Но сначала сделаем небольшое отступление.
Привязка к пикселям
На демо видно, что верхний край макбука выглядит чётче на примере с top/left
(а статья вроде бы о том, что translate
лучше. Замечательно!) Это происходит из-за того, что абсолютное позиционирование привязывается к позициям пикселей, а translate
использует субпиксельную интерполяцию.
Один из разработчиков подсистемы аппаратного ускорения Chrome, Джеймс Робинсон, называет это «дабстеп-эффектом», так как элементы словно вибрируют от низких частот во время движения. Если сделать смещение по одной из осей маленьким, всего в три пикселя, разница становится очень заметной:
Слева хорошо заметны прыжки по пиксельной сетке. Возможно, в этом примере такой вариант выглядит лучше, хотя с менее контрастным изображением это могло бы быть не так заметно.
Вернёмся к производительности
Если открыть timeline в инструментах разработчика Chrome, эти два примера будут выглядеть совершенно по-разному:
Вариант с top/left
тратит очень много времени на отрисовку, и движение получается более дёрганым. В стилях прописаны крупные тени, а фон представляет собой сложный градиент, и всё это обсчитывается на CPU. С другой стороны, translate
рисует макбук на отдельном слое, все двух- или трёхмерные преобразования делаются на GPU, что намного быстрее, и позволяет получить более плавное движение.
Ближе к концу видео я подробно останавливаюсь на этих моментах и показываю, как можно измерить время отрисовки, посмотреть, какие области перерисовываются, и в каких случаях используется GPU.
Демо
Вы можете добавить больше слоёв, чтобы эффект был более выраженным. Откройте timeline и поэкспериментируйте:
Рекомендации для анимации
- Используйте анимации и переходы CSS, когда возможно. Браузер очень хорошо умеет их оптимизировать.
- Если необходимо делать анимацию через JavaScript, используйте
requestAnimationFrame
вместоsetTimeout
иsetInterval
. - Старайтесь не менять стили каждый кадр (как это делалось в jQuery
animate()
), анимации, заданные декларативно в CSS оптимизируются намного лучше. - Использование 2D-трансформаций вместо абсолютного позиционирования обычно обеспечивает большую частоту кадров за счёт более быстрого рендеринга.
- Пользуйтесь timeline, чтобы находить и устранять проблемы с производительностью.
- Опции «Show Paint Rects» и «Render Composited Layer Borders» полезны, когда надо узнать, какие именно области перерисовываются.
Автор: ilya42