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

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

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

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

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

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

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

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

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

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

Элементы также можно вращать, в примере ниже на 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 это свойство можно применить к любому селектору:

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

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

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

Отладка медленной или прерывистой анимации

В Chrome DevTools и Firefox DevTools есть множество инструментов, которые помогут вам выяснить, почему ваша анимация медленная или дерганная.

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

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

Не
.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. Остановите запись и проверьте вкладку «Водопад» .

Если вы видите записи для «Пересчитать стиль» , значит, браузер должен начать с начала каскада рендеринга .

Проверьте, не пропускает ли анимация кадры

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

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

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

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

Когда дело доходит до живописи, некоторые вещи стоят дороже, чем другие. Например, рисование всего, что связано с размытием (например, тени), займет больше времени, чем рисование красного прямоугольника. Однако с точки зрения CSS это не всегда очевидно: background: red; и box-shadow: 0, 4px, 4px, rgba(0,0,0,0.5); не обязательно выглядит так, будто у них совершенно разные характеристики производительности, но они есть.

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

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

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

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

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

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

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

Заключение

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

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

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