CSS-свойство will-change
Используйте CSS-свойство will-change, чтобы указать браузеру, как элемент будет изменяться в будущем. Читайте описание и смотрите примеры.
Свойство will-change даёт браузеру подсказку о том, как элемент, вероятно, изменится в ближайшем будущем, чтобы браузер мог настроить необходимые оптимизации заранее — а не пытаться успеть к тому самому кадру, когда изменение уже началось.
На этой странице рассматривается, что делает will-change, когда (и когда не следует) к нему обращаться, допустимые значения, рабочий пример и подводные камни, делающие это свойство легко поддающимся злоупотреблению.
Зачем нужно will-change
Такие свойства, как transform и opacity, дёшево анимировать, потому что браузер может перенести элемент на собственный compositing layer (отдельную поверхность, которую GPU может перемещать, затухать или масштабировать без перерисовки остальной страницы). Однако создание этого слоя стоит времени и памяти. Если браузер обнаруживает, что слой нужен, лишь в момент начала анимации, первый кадр может дёрнуться.
will-change позволяет заранее сообщить браузеру, какие свойства вот-вот изменятся, чтобы он мог подготовить слой заблаговременно и анимация была плавной с самого первого кадра.
Значения разделяются запятыми. Свойство will-change принимает следующие значения: auto, <custom-ident> — например, имя свойства (transform, opacity, scroll-position, …), initial, inherit или unset.
Это свойство следует использовать с осторожностью. Разные браузеры обрабатывают его по-разному, и чрезмерное использование может привести к тому, что браузер его проигнорирует. Злоупотребление также может создать ненужные compositing layer'ы, увеличив потребление памяти и снизив производительность.
Правильное использование свойства will-change
- Не применяйте его к слишком большому количеству элементов. Каждая подсказка
will-changeможет заставить браузер держать compositing layer активным, что расходует память. Если дать подсказку для сотен элементов, страница может замедлиться, а не ускориться. - Добавляйте и убирайте его через скрипт, вокруг изменения. Устанавливайте
will-changeнезадолго до изменения (например, по событиюmouseenterилиfocus), а затем удаляйте его после завершения анимации, чтобы браузер мог освободить слой. - Не используйте его как преждевременную оптимизацию. Если страница уже анимируется плавно, оставьте её в покое. Прибегайте к
will-changeтолько для устранения измеренной проблемы с производительностью — это последнее средство, а не значение по умолчанию. - Дайте браузеру время на подготовку. Смысл
will-change— предупредить браузер заблаговременно. Устанавливать его на том же кадре, что и начало анимации, бессмысленно. - Учитывайте влияние на отрисовку. Значения, создающие stacking context (например,
will-change: opacityилиwill-change: transform), могут изменить порядок наложения элемента относительно соседей — точно так же, как если бы вы фактически задали эти свойства.
| Начальное значение | auto |
|---|---|
| Применяется к | Всем элементам. |
| Наследуется | Нет. |
| Анимируемое | Нет. |
| Версия | CSS Transitions Module Level 1 |
| DOM-синтаксис | object.style.willChange = "transform"; |
Примечание: в JavaScript имя свойства записывается в camelCase (willChange), тогда как в CSS — через дефис (will-change).
Синтаксис
Значения CSS will-change
will-change: auto | <custom-ident> | initial | inherit | unset;Пример свойства will-change:
Пример кода CSS will-change
<!DOCTYPE html>
<html>
<head>
<title>The title of the document</title>
<style>
.circle {
width: 50px;
height: 50px;
transform: translate(50px, 0px);
border-radius: 30px;
}
.circle.blue {
background: #1c87c9;
will-change: transform;
}
.circle.green {
background: #8ebf42;
}
</style>
</head>
<body>
<h2>Will-change property example</h2>
<div class="circle green"></div>
<div class="circle blue"></div>
<div class="circle green"></div>
<div class="circle blue"></div>
<div class="circle green"></div>
<script>
const circles = document.getElementsByClassName("circle blue");
function update(t) {
for (let i = 0; i < circles.length; i++) {
const xpos = Math.sin(t / 1000 + 1000 * i) * 50 + 50;
circles[i].style.transform = "translate(" + xpos + "px, 0px)";
}
window.requestAnimationFrame(update);
}
update();
</script>
</body>
</html>Установка и сброс will-change через скрипт
Рекомендуемый подход — добавлять подсказку непосредственно перед взаимодействием и удалять её после, чтобы браузер удерживал слой только тогда, когда это необходимо:
.card {
transition: transform 0.3s;
}
/* Hint the browser only while the user hovers. */
.card:hover {
will-change: transform;
transform: scale(1.05);
}Для длительных или управляемых JavaScript анимаций переключайте его в коде:
const el = document.querySelector(".card");
// Prepare ahead of the change.
el.addEventListener("mouseenter", () => {
el.style.willChange = "transform";
});
// Release the optimization once it's no longer needed.
el.addEventListener("animationend", () => {
el.style.willChange = "auto";
});Значения
| Значение | Описание |
|---|---|
| auto | Применяется стандартная оптимизация браузера. |
<custom-ident> | Задаёт CSS-свойство, которое, как ожидается, изменится или будет анимировано на элементе в ближайшем будущем. Если свойство является сокращённым (shorthand), изменения распространятся на все его полные (longhand) свойства. |
| initial | Устанавливает для свойства его значение по умолчанию. |
| inherit | Наследует свойство от родительского элемента. |
| unset | Сбрасывает свойство до унаследованного или начального значения в зависимости от свойства. |
Связанные свойства
will-change — это подсказка для оптимизации свойств, которые вы фактически анимируете. Оно естественно сочетается со следующими свойствами:
transform— наиболее распространённая цельwill-change, поскольку трансформации хорошо обрабатываются GPU.opacity— также компонуется и часто используется для эффектов затухания.transitionиanimation— механизмы, управляющие изменениями, о которых вы даёте подсказку.z-index— актуально, поскольку некоторые значенияwill-changeсоздают новый stacking context.