Введение в свойство CSS will-change
HTML&CSS

Введение в свойство CSS will-change

Оригинал: An Introduction to the CSS will-change Property, Nick Salloum

В этой статье мы рассмотрим свойство CSS will-change, зачем, когда и как его использовать, и как его не использовать. Документации по этому свойству совсем немного, я буду ссылаться на эти ресурсы в статье, а в конце приведен список источников. В статье представлен обзор важных особенностей свойства will-change с небольшими примерами.

Основы

Сегодня многие фронтенд-разработчики используют плавные переходы, трансформации и анимацию CSS3, реализуя интерактивные элементы, которые раньше требовали использования JavaScript или Flash. Теперь мы можем добавлять мягкие и красивые анимации с минимумом CSS. Если вы экспериментируете с этими свойствами, вы наверняка уже столкнулись с понятиями CPU, GPU и аппаратное ускорение. Давайте кратко рассмотрим эти понятия:

  • CPU (Central Processing Unit), или центральный процессор — часть оборудования, которая обрабатывает почти все операции компьютера.
  • GPU (Graphics Processing Unit), или графический процессор — часть оборудования, которая отвечает за обработку и отображение графики. GPU предназначен для выполнения сложных графических вычислений и снимает эту нагрузку с процессора.
  • Аппаратное ускорение это общий термин для разгрузки центрального процессора, когда часть операций выполняется каким-либо другим оборудованием. В мире переходов, преобразований и анимации CSS это означает, что эти операции выполняются на GPU, и, следовательно, происходит ускорение. Для этого элемент перемещается на свой отдельный «слой», где он может отрисовываться во время анимации независимо от остальной страницы.

Как можно улучить производительность и качество анимации? В webkit-браузерах мы можем видеть мирцание во время 2D трансформации или анимации. Раньше для этого использовался небольшой трюк. Мы говорим браузеру, что выполняется 3D-трансформация, тем самым заставляем его перенести эту операцию на графический процессор, поскольку 3D-трансформации автоматически вычисляются на графическом процессоре. Это можно реализовать с помощью небольшого трюка:


.accelerate {
    -webkit-transform: translate3d(0, 0, 0);
}

Есть и другие подобные приемы. Тем не менее, это хак, а свойство will-change, при правильном использовании, может помочь избавится от него. Давайте разберемся.

Что такое will-change?

Согласно черновику спецификации W3C :

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

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

Как использовать свойство will-change?

Свойство will-change эффективно только тогда, когда применяется за некоторое время до начала трансформации. Мы не можем применить что-то вроде will-change: transform к уже трансформирующемуся элементу — в этом просто нет смысла. Сара Суэдан удивительно подробно рассказывает об этом в блоге Opera , обязательно почитайте, но ключевые моменты этого поста ниже:

  • Свойство will-change используется, чтобы заранее информировать браузер о том, каких изменений можно ожидать от элемента.
  • Это свойство позволяет браузеру сделать необходимую оптимизацию заранее, что в конечном итоге приводит к более быстрому рендерингу.
  • Как упоминалось ранее, браузер должен знать заранее, что произойдет изменение. Это означает, что мы должны думать заранее, когда подготавливаем браузер к изменениям.

С учетом указанных выше пунктов, давайте рассмотрим пример, который не будет иметь никакого эффекта:


.will-change:active {
    will-change: transform;
    transition: transform 0.3s;
    transform: scale(1.5);
}

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

Для элемента в состоянии active, как в примере, это можно сделать при наступлении состояния hover. Мы может сделать что-то вроде этого:


.will-change {
    transition: transform 0.3s;
}

.will-change:hover {
    will-change: transform;
}

.will-change:active {
    transform: scale(1.5);
}

Этот небольшой пример дает некоторое представление о мыслительном процессе, который необходим для правильного использования свойства will-change. Но прежде чем мы продолжим рассмотрение примеров, необходимо разобраться с некоторыми важными аспектами.

Браузеры, сами по себе, стараются максимально оптимизировать отрисовку и быть готовыми к изменениям. Некоторые оптимизации они могут удалять, чтобы освободить память. Использование свойства will-change непосредственно на элементе говорит о том, что данный элемент очень близок к изменению в данный момент. Это заставляет браузер поддерживать оптимизации, тем самым увеличивая потребление памяти. Имея это в виду, мы должны иметь способ добавления и удаления свойства will-change в нужное время. В примере выше все правильно, потому что will-change добавляются только при наведении. Но что, если мы хотим применить преобразование при наведении? Можно было бы попытаться сделать так:


.will-change {
    will-change: transform;
    transition: transform 0.3s;
}

.will-change:hover {
    transform: scale(1.5);
}

Это приведет к увеличению потребления памяти, потому что таким способом мы заставляем браузер думать, что элемент все время близок к изменению. Обойти это можно, добавляя will-change, когда родительский элемент переходит в состояние hover:


.will-change-parent:hover .will-change {
    will-change: transform;
}

.will-change {
    transition: transform 0.3s;
}

.will-change:hover {
    transform: scale(1.5);
}

В этом примере оптимизация добавляется, когда курсор мыши попадает на родительский контейнер, и удаляется, когда курсор мыши покидает его. Здесь также подразумевается, что каждый раз, когда курсор входит в родительский контейнер, браузер должен ожидать изменения в элементе. А это не обязательно так. Это совершенно ясный пример того, как легко злоупотребить свойством will-change.

Построение полноэкранного слайд-шоу или перелистываемой книги на CSS — примеры того, когда может работать прямое применение will-change. Слайды всегда могут измениться, поэтому здесь подойдет такой вариант:


.slide {
    will-change: transform;
}

Всегда удаляйте will-change

Никогда не забывайте удалять свойство will-change после окончания изменений. Как я уже упоминал выше, оптимизация в браузере является дорогостоящим процессом. Поэтому, когда она используется неаккуртно, она может иметь негативные последствия. Исправить ситуацию можно с помощью JavaScript, в примере нижие я использовал сценарий из MDN . Представьте, у нас есть элемент с классом .element, и, когда мы нажимаем на него, он трансформируется. CSS будет выглядеть так:


.element {
    transition: transform 0.5s;
}

.element.clicked {
    transform: scale(1.5);
}

Если мы хотим уведомить браузер для подготовки к изменению, которое вот-вот произойдет в ответ на щелчок по элементу, мы можем сделать так:


var el = document.querySelector('.element');

el.addEventListener('mouseenter', hintBrowser);
el.addEventListener('animationEnd', removeHint);

function hintBrowser() {
    this.style.willChange = 'transform';
}

function removeHint() {
    this.style.willChange = 'auto';
}

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

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

Свойство will-change довольно новое, согласно Can I Use на данный момент поддерживается следующими браузерами:

  • Chrome 36 and up
  • Firefox 36 and up
  • Opera 24 and up
  • Android browser 37
  • Chrome for Android 40
  • Opera Mobile 24

В Internet Explorer свойство will-change на момент написания этой статьи находилось в списке рассматриваемых.

Заключение и список источников

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

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

Рассылка
Подпишитесь на рассылку и получайте дайджест новостей и статей.
Никакого спама!
Подписаться