CSS-свойство will-change используется для информирования
браузера о том, какие свойства элемента, вероятно, будут изменяться в
ближайшем будущем. Это позволяет движку рендеринга заранее подготовить
оптимизации, создавая отдельные слои или активируя аппаратное ускорение,
что снижает стоимость последующих изменений и повышает плавность
анимаций.
В современных браузерах рендеринг страницы разделяется на несколько этапов: расчёт стилей, построение дерева рендеринга, компоновка (layout), рисование (paint) и композитинг (compositing). Некоторые CSS-свойства требуют перерасчёта всех этапов, включая layout, что является дорогой операцией.
will-change позволяет браузеру предсказать изменения и
заранее перевести элемент в более «лёгкий» для анимации режим. Чаще
всего это означает:
Основной эффект достигается при изменении свойств, таких как
transform, opacity, filter.
.element {
will-change: transform;
}
Допускается указание нескольких свойств:
.element {
will-change: transform, opacity;
}
Также возможно значение auto, которое возвращает
браузеру право самостоятельно решать оптимизации:
.element {
will-change: auto;
}
Наибольший эффект достигается при использовании свойств, не вызывающих перерасчёт layout:
transformopacityfiltertop, left (в ограниченных случаях, менее
эффективно)scroll-position (в специфичных реализациях
браузеров)Наиболее производительный подход связан с transform, так
как он почти полностью обрабатывается на этапе compositing.
При анимациях элементов через JavaScript-библиотеки, такие как
Velocity.js, will-change часто используется для подготовки
элемента перед стартом анимации.
Velocity.js активно оптимизирует анимации через
transform и opacity, что делает его
совместимым с GPU-композитингом.
Пример анимации появления:
Velocity(element, {
opacity: 1,
translateY: "0px"
}, {
duration: 300
});
Оптимизация с will-change перед запуском:
element.style.willChange = "transform, opacity";
Velocity(element, {
opacity: 1,
translateY: "0px"
}, {
duration: 300
});
После завершения анимации свойство необходимо сбрасывать:
element.style.willChange = "auto";
Правильное использование will-change связано с временным
включением оптимизации:
will-change перед стартомПостоянное применение свойства приводит к перерасходу памяти из-за удержания дополнительных compositor layers.
При корректном использовании достигаются следующие эффекты:
Однако чрезмерное использование приводит к обратному эффекту:
Особенно критично применение к большому числу элементов одновременно (например, списки или сетки).
Одной из распространённых ошибок является глобальное применение:
* {
will-change: transform;
}
Такой подход приводит к созданию множества слоёв, которые никогда не используются для анимации.
Ещё одна ошибка — постоянное объявление свойства без реальной необходимости:
.card {
will-change: transform;
}
если анимация происходит редко или отсутствует вовсе.
Более корректный подход заключается в управлении свойством в момент взаимодействия пользователя или перед анимацией.
Пример с hover-состоянием:
button.addEventListener("mouseenter", () => {
button.style.willChange = "transform";
});
button.addEventListener("mouseleave", () => {
button.style.willChange = "auto";
});
Такой подход ограничивает время существования дополнительных слоёв.
Velocity.js позволяет строить последовательные и параллельные
анимации, где will-change может применяться точечно перед
каждой фазой.
Пример последовательной анимации:
element.style.willChange = "transform, opacity";
Velocity(element, {
translateX: "100px"
}, {
duration: 200
});
Velocity(element, {
opacity: 0.5
}, {
duration: 200,
complete: function () {
element.style.willChange = "auto";
}
});
В сценариях с высокой частотой обновления (drag & drop, scroll
animations) will-change особенно эффективен при
предварительном включении оптимизации до начала взаимодействия.
При обработке скролла элементы часто подвергаются непрерывным
изменениям transform. В таких случаях использование
will-change позволяет избежать постоянных перерасчётов
layout.
Пример:
window.addEventListener("scroll", () => {
element.style.transform = `translateY(${window.scrollY * 0.5}px)`;
});
Оптимизированная версия:
element.style.willChange = "transform";
window.addEventListener("scroll", () => {
element.style.transform = `translateY(${window.scrollY * 0.5}px)`;
});
Каждое использование will-change потенциально создаёт
новый слой композитинга. Эти слои:
Избыточное количество слоёв приводит к давлению на видеопамять и может снижать производительность даже на мощных устройствах.
Эффективные анимации строятся на следующих принципах:
transform вместо изменения геометрии
(width, height, top)will-changeVelocity.js хорошо вписывается в такую архитектуру благодаря работе с оптимизированными CSS-свойствами и внутреннему управлению очередями анимаций.
Реализация will-change может отличаться:
Это означает, что эффект не гарантирован, а является рекомендацией для движка, а не строгим указанием.
Наилучшие результаты достигаются при совместном использовании:
transform: translate3d() (в некоторых сценариях)opacity для плавных переходовrequestAnimationFrame для синхронизации с кадромwill-change в этой связке выступает как предварительный
сигнал оптимизации, а не основной механизм ускорения.