Xiper

Оптимизация DOM анимации

Автор: Евгений Рыжков Дата публикации:
Последнее обновление:

Постарался упорядочить действия, направленные на оптимизацию DOM/CSS анимации, в порядке эффективности. Чем выше оптимизация в списке, тем больший прирост производительности она обычно дает.

1. Изоляция анимируемого блока

По максимуму стараемся изолировать анимируемый блок, тем самым сокращаем количество элементов участвующих в анимации.

Оборачиваем анимированный участок в контейнер с четко заданным набором CSS свойств:

2. Сокращение количество reflow, repaint, recalculate

Оптимизируем неэффективные участки Javascript:

  • свести к минимуму манипуляции с DOM (добавление/удаление/поиск узлов);
  • innerHTML или innerHTML + join (собирать строки через join, а не обычным +) вместо многочисленных appendChild;
  • кешируем значения свойств объектов, особенно таких как размеры (offsetWidth, offsetHeight ) и положение (offsetTop, offsetLeft, scrollTop, scrollLeft, scrollWidth, scrollHeight, clientTop, clientLeft, clientWidth, clientHeight), а также получение всех текущих стилей (getComputedStyle / currentStyle). Приводит к принудительным reflow и repaint;
  • изменение CSS свойств одной операцией (добавление класса или cssText);
  • изменение свойств объектов делать в скрытых блоках, а так же группировать изменения;
  • анимацию лучше делать с абсолютно позиционируемыми элементами;
  • эффективное использование таймеров, а еще лучше - requestAnimationFrame (для IE10, FF, Chrome, Safari6, iOs 5+).

3. Избавиться от тяжелых CSS3 свойств

4. Сократить количество DOM узлов, участвующих в анимации

Индивидуально для каждого случая. Например, если в данный момент пользователь не видит какие-то элементы, их можно удалить из DOM перед анимацией.

5. Аппаратное ускорение

Включается при использовании CSS transform и CSS keyframes. Включается у FF, Chrome, Safari, Opera (ей не оч помогает), заявлено IE10.

Если после этой оптимизации все еще прилично тормозит, далее идти нет смысла. Нужно либо что-то еще пробовать по вышеперечисленным, либо пересматривать сценарий анимации в целом.

6. Сократить глубину DOM узлов в анимируемом блоке

Хорошо подумать и переверстать. Возможно что-то упростить в дизайне, возможно что-то реализовать на JS. По возможности избавится от таблиц.

7. Размеры изображениям

Указывая четкие размеры изображениям ускоряем reflow и repaint.

8. Сократить/оптимизировать CSS

  • удалить неиспользуемые селекторы/правила;
  • избавиться от универсальных селекторов;
  • селекторы для конкретных классов/id, без каскадов (см. об эффективности CSS селекторов);
  • не использовать float для разметки (личным опытом пока не подтверждено);
  • в таблицах четкие размеры в сочетании с table-layout: fixed (личным опытом пока не подтверждено).

проанализировать эффективность CSS поможет csslint.

Если ничего не помогло

Пересмотреть сценарий анимации и/или дизайн.

Некоторые наблюдения / заметки

  • общий контейнер позиционировать абсолютом. Иначе перерисовываться будет весь экран. (если в анимации происходят layout для общего контейнера). например, slideDown;
  • анимации с изменением размеров элементов, перемещением, изменение прозрачности, размера шрифта будут всегда затратнее, чем изменение оформления т.к. в потребуется layout;
  • избегать анимации затрагивающие геометрию body (перекомпановка/перерисовка всего);
  • работа с documentFragment и виртуальным DOM элементом (createElement) по производительности примерно одинакова;
  • если в поле есть placeholder, то идет reflow (хром как минимум). Производительность падает незначительно (если поле одно);
  • на reflow/repaint нужны ресурсы и время. Например, вставляя крупный DOM узел и в это время производить анимацию вряд ли получится даже для мощного железа.

Материалы

  • Reflows & Repaints: CSS Performance making your JavaScript slow?
  • Скорость рендеринга страниц: исследования, замеры, автоматизация
  • Rendering: repaint, reflow/relayout, restyle