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

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

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

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

transform

Поддержка браузера

  • Хром: 36.
  • Край: 12.
  • Фаерфокс: 16.
  • Сафари: 9.

Источник

opacity

Поддержка браузера

  • Хром: 1.
  • Край: 12.
  • Фаерфокс: 1.
  • Сафари: 2.

Источник

will-change

Поддержка браузера

  • Хром: 36.
  • Край: 79.
  • Фаерфокс: 36.
  • Сафари: 9.1.

Источник

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

Чтобы переместить элемент, используйте значения ключевых слов 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 (скорее всего, в Internet Explorer), вы можете установить transform: translateZ(0) .

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

В Chrome DevTools и 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));
  }
}

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

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

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

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

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

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

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

  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, но инструменты разработчика браузера могут помочь вам определить, какие области необходимо перерисовать, а также другие проблемы с производительностью, связанные с отрисовкой.

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

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

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

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

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

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

Заключение

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

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

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