Что предпочтительнее для анимации: left/top или transform и почему
Что проверяют
Знаете ли вы конвейер рендеринга и какие свойства на каком его этапе отрабатывают. Это не вопрос про синтаксис, а проверка понимания, почему анимация дёргается и что с этим делать.
Как отвечать
Кадр собирается в три шага: расчёт раскладки, отрисовка, композиция слоёв. Анимация left и top меняет геометрию, поэтому каждый кадр требует пересчёта раскладки и новой отрисовки области. transform и opacity геометрию не меняют и при наличии собственного слоя обрабатываются на этапе композиции, часто в отдельном потоке, поэтому кадры не срываются даже когда основной поток занят.
/* дёргается: раскладка пересчитывается каждый кадр */
.a { transition: left 0.3s; }
/* плавно: работает только композиция */
.b { transition: transform 0.3s; }Отсюда практика: сдвиг через translate, появление через opacity, изменение размера через scale вместо width и height. Браузер сам создаёт слой под анимацию, подсказать можно свойством will-change, но не на десятках элементов сразу: каждый слой стоит памяти. Проверяется всё в панели производительности браузера по тому, появляются ли в кадре пересчёты раскладки.
Где спотыкаются
Считают, что left и top двигают соседние элементы. У относительно позиционированного элемента смещение соседей не трогает, у абсолютно позиционированного он вообще вне потока. Проблема не в потоке, а в пересчёте раскладки на каждом кадре.
Второе: верят, что transform всегда считает видеокарта. Нужен отдельный слой, и его может не быть, а тяжёлая тень или фильтр на большом элементе всё равно упрутся в отрисовку. Промотирование всего подряд через will-change или трюк с нулевым сдвигом по третьей оси делает только хуже.
Третье: забывают про чередование чтения и записи. Если сразу после изменения стилей прочитать геометрию через getBoundingClientRect или offsetTop, браузер вынужден пересчитать раскладку немедленно. Анимация проседает не из-за выбранного свойства, а из-за такого цикла: сначала все чтения, потом все записи.