Как создавать высокопроизводительную CSS-анимацию

В этом руководстве вы узнаете, как создавать высокопроизводительные CSS-анимации.

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

Совместимость с браузерами

Все свойства CSS, рекомендуемые в этом руководстве, имеют хорошую кроссбраузерную поддержку.

transform

Browser Support

  • Хром: 36.
  • Край: 12.
  • Firefox: 16.
  • Сафари: 9.

Source

opacity

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 1.
  • Сафари: 2.

Source

will-change

Browser Support

  • Хром: 36.
  • Край: 79.
  • Firefox: 36.
  • Сафари: 9.1.

Source

Переместить элемент

Чтобы переместить элемент, используйте ключевые слова translate или rotation свойства transform .

Например, чтобы вывести элемент на экран, используйте translate .

.animate {
  animation: slide-in 0.7s both;
}

@keyframes slide-in {
  0% {
    transform: translateY(-1000px);
  }
  100% {
    transform: translateY(0);
  }
}

Используйте rotate для вращения элементов. Следующий пример вращает элемент на 360 градусов.

.animate {
  animation: rotate 0.7s ease-in-out both;
}

@keyframes rotate {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}

Изменить размер элемента

Чтобы изменить размер элемента, используйте значение ключевого слова scale свойства transform .

.animate {
  animation: scale 1.5s both;
}

@keyframes scale {
  50% {
    transform: scale(0.5);
  }
  100% {
    transform: scale(1);
  }
}

Изменить видимость элемента

Чтобы показать или скрыть элемент, используйте opacity .

.animate {
  animation: opacity 2.5s both;
}

@keyframes opacity {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

Избегайте свойств, которые вызывают изменение макета или рисования

Прежде чем использовать какое-либо свойство CSS для анимации (кроме transform и opacity ), определите влияние свойства на конвейер рендеринга . Избегайте любого свойства, которое запускает макет или отрисовку, если это не является абсолютно необходимым.

Создание слоя силы

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

Браузеры обычно могут принимать правильные решения о том, какие элементы следует разместить на новом слое, но вы можете вручную принудительно создать слой с помощью свойства will-change . Как следует из названия, это свойство сообщает браузеру, что этот элемент будет каким-то образом изменен.

В CSS вы можете применить will-change к любому селектору:

body > .sidebar {
  will-change: transform;
}

Однако спецификация предполагает, что вы должны добавлять это только к элементам, которые всегда будут меняться. Например, это может быть использовано для боковой панели, которую пользователь может выдвигать и задвигать. Если элемент не меняется часто, примените will-change с помощью JavaScript, когда изменение, скорее всего, произойдет. Обязательно дайте браузеру достаточно времени для выполнения необходимых оптимизаций и удалите свойство, когда изменение прекратится.

Чтобы принудительно создать слой в браузере без поддержки will-change , можно задать transform: translateZ(0) .

Отладка медленной или глючной анимации

Инструменты разработчика Chrome и Firefox DevTools помогут вам выяснить, почему анимация работает медленно или глючит.

Проверьте, вызывает ли анимация изменение макета

Анимация, которая перемещает элемент с помощью чего-то, отличного от transform скорее всего, будет медленной. В следующем примере сравнивается анимация с использованием transform с анимацией с использованием top и left .

Не
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     top: calc(90vh - 160px);
     left: calc(90vw - 200px);
  }
}
Делать
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     transform: translate(calc(90vw - 200px), calc(90vh - 160px));
  }
}

Вы можете протестировать это в следующих двух примерах и изучить производительность с помощью DevTools.

Инструменты разработчика Chrome

  1. Откройте панель «Производительность» .
  2. Записывайте производительность во время выполнения анимации.
  3. Проверьте вкладку «Сводка» .

Если на вкладке «Сводка» вы видите ненулевое значение параметра «Рендеринг» , это может означать, что ваша анимация заставляет браузер выполнять работу по компоновке.

Панель «Сводка» показывает 37 мс для рендеринга и 79 мс для отрисовки.
Пример анимации с верхним левым углом вызывает работу по рендерингу.
На панели «Сводка» отображаются нулевые значения для рендеринга и покраски.
Пример анимации с преобразованием не требует рендеринга.

Инструменты разработчика Firefox

В Firefox DevTools метод Waterfall поможет вам понять, на что браузер тратит время.

  1. Откройте панель «Производительность» .
  2. Начните записывать выступление во время создания анимации.
  3. Остановите запись и проверьте вкладку «Водопад» .

Если вы видите записи для Recalculate Style , это означает, что браузер должен вернуться к началу каскада рендеринга , чтобы отобразить анимацию.

Проверьте наличие пропущенных кадров

  1. Откройте вкладку «Рендеринг» в Chrome DevTools.
  2. Установите флажок «Измеритель FPS» .
  3. Следите за значениями во время воспроизведения анимации.

Обратите внимание на метку Кадры в верхней части пользовательского интерфейса счетчика FPS . Она показывает значения, например, 50% 1 (938 m) dropped of 1878 Высокопроизводительная анимация имеет высокий процент, например 99% , что означает, что сбрасывается мало кадров и анимация выглядит плавной.

Счетчик кадров в секунду показывает, что 50% кадров были потеряны.
Пример анимации с верхним левым углом приводит к потере 50% кадров
Счетчик кадров в секунду показывает, что был потерян только 1% кадров.
В примере анимации с преобразованием теряется всего 1% кадров.

Проверьте, вызывает ли анимация рисование

Некоторые свойства обходятся браузеру дороже, чем другие. Например, все, что связано с размытием (например, тень), отрисовывается дольше, чем красная рамка. Эти различия не всегда очевидны в CSS, но браузерные DevTools могут помочь вам определить, какие области нужно перерисовать, а также другие проблемы производительности, связанные с отрисовкой.

Инструменты разработчика Chrome

  1. Откройте вкладку «Рендеринг» в Chrome DevTools.
  2. Выберите опцию «Окраска» .
  3. Перемещайте указатель по экрану.
Элемент пользовательского интерфейса, выделенный зеленым цветом, чтобы показать, что он будет перерисован.
В этом примере из Google Maps вы можете видеть, как перерисовываются элементы.

Если вы видите, что весь экран мигает или выделены области, которые, по вашему мнению, не должны меняться, проведите дальнейшее исследование.

Если вам необходимо определить, вызывает ли определенное свойство проблемы с производительностью, связанные с отрисовкой, вам поможет профилировщик отрисовки в Chrome DevTools.

Инструменты разработчика Firefox

  1. Откройте «Настройки» и добавьте кнопку «Панель инструментов» для включения/выключения мерцания краски .
  2. На странице, которую вы хотите проверить, включите кнопку и переместите мышь или прокрутите страницу, чтобы увидеть выделенные области.

Анимация на этапе компоновки

Где возможно, ограничьте анимации opacity и transform , чтобы сохранить анимации на этапе компоновки пути рендеринга. Используйте DevTools, чтобы проверить, на какой этап пути влияют ваши анимации.

Используйте профилировщик рисования, чтобы увидеть, являются ли какие-либо операции рисования особенно затратными. Если вы что-то обнаружите, проверьте, дает ли другое свойство CSS тот же вид и ощущение с лучшей производительностью.

Используйте свойство will-change экономно и только в случае возникновения проблем с производительностью.