Pull to refresh

Почему перемещать элементы с помощью translate лучше, чем с position:absolute top/left

Reading time 2 min
Views 36K
Original author: Paul Irish
Для перемещения элемента по экрану есть два основных способа:

  • 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 и поэкспериментируйте:



Рекомендации для анимации


  1. Используйте анимации и переходы CSS, когда возможно. Браузер очень хорошо умеет их оптимизировать.
  2. Если необходимо делать анимацию через JavaScript, используйте requestAnimationFrame вместо setTimeout и setInterval.
  3. Старайтесь не менять стили каждый кадр (как это делалось в jQuery animate()), анимации, заданные декларативно в CSS оптимизируются намного лучше.
  4. Использование 2D-трансформаций вместо абсолютного позиционирования обычно обеспечивает большую частоту кадров за счёт более быстрого рендеринга.
  5. Пользуйтесь timeline, чтобы находить и устранять проблемы с производительностью.
  6. Опции «Show Paint Rects» и «Render Composited Layer Borders» полезны, когда надо узнать, какие именно области перерисовываются.


Tags:
Hubs:
+42
Comments 24
Comments Comments 24

Articles