will-change: подсказка браузеру о будущей анимации

will-change заранее подсказывает браузеру, какое свойство элемента вот-вот изменится, чтобы он успел подготовить отдельный композитный слой ДО начала анимации, а не во время неё. Звучит как простая оптимизация, но у неё есть реальная цена: лишний слой ест память браузера, а сам факт добавления will-change создаёт у элемента новый контекст наложения - и меняет то, как ведёт себя z-index у его потомков, что легко ловит врасплох.

Попробуй прямо сейчас: карточка поднимается при наведении так же плавно, как и без will-change (для одиночного простого hover-эффекта на transform разницы почти нет - он и так анимируется легко, см. прошлый урок). Удали строку will-change: transform полностью и наведи снова - анимация останется такой же плавной. В этом и суть: will-change не делает анимацию "более плавной" сама по себе, она лишь заранее готовит браузер, и польза от неё заметна только в тяжёлых сценариях, а не на одной простой карточке.

Что делает will-change и почему это не бесплатно

will-change принимает auto (по умолчанию, без подсказки), имя одного или нескольких CSS-свойств через запятую (чаще всего transform или opacity), scroll-position (для прокручиваемых контейнеров) или contents (для часто меняющегося содержимого). Указанное значение говорит браузеру: "скоро это свойство изменится - продвинь элемент в отдельный композитный слой заранее", чтобы подготовка слоя не съедала время уже во время самой анимации.

.slider-track { will-change: transform; } - элемент, который двигается практически постоянно (лента слайдера), браузер заранее держит наготове.

Побочный эффект, о котором MDN предупреждает абстрактно ("может неожиданно повлиять на z-index"), проверен здесь конкретными пикселями. Без will-change контейнер с position: relative (но без z-index) НЕ создаёт собственный контекст наложения - поэтому дочерний элемент с z-index: -1 внутри него может "провалиться" ниже соседнего элемента того же уровня, если тот идёт раньше по DOM. Стоит добавить will-change: transform на контейнер - и он ТОЖЕ создаёт контекст наложения, в точности как это сделал бы настоящий transform. Тот же самый дочерний элемент с тем же z-index: -1 больше не может провалиться ниже уровня своего контейнера - он остаётся привязан к его локальному контексту наложения.

.container { position: relative; } .child { position: relative; z-index: -1; } /* .child может уйти позади соседнего элемента вне .container */

.container { position: relative; will-change: transform; } .child { position: relative; z-index: -1; } /* .child теперь "заперт" внутри контекста наложения .container */ - собственная проверка (Playwright, сравнение пикселя в точке перекрытия): цвет в этой точке реально меняется на противоположный только от добавления одной строки will-change, без единого другого изменения кода.

Когда will-change действительно стоит применять

Главное предупреждение MDN стоит помнить дословно: will-change нужно использовать как последнее средство для решения УЖЕ СУЩЕСТВУЮЩЕЙ проблемы с производительностью, а не для того, чтобы предугадать её заранее. Каждый элемент с will-change - это лишний слой, который занимает память браузера, и если развесить эту подсказку на многие элементы "про запас", суммарный эффект может замедлить страницу вместо того, чтобы её ускорить - ровно противоположный результат.

Как уже разбиралось в прошлом уроке про производительность анимаций, transform и opacity и без того легко анимируются сами по себе - composite-only, без Layout и Paint. Добавлять will-change ради одиночного простого hover-эффекта на transform - это именно та преждевременная оптимизация, против которой предупреждает MDN, реального выигрыша почти нет.

"Золотой стандарт" применения - включать will-change непосредственно перед началом анимации через JavaScript и выключать (will-change: auto) сразу после её завершения, чтобы слой не занимал память дольше необходимого. Этот курс держится без JavaScript, поэтому практичный компромисс - держать will-change прямо в таблице стилей ТОЛЬКО для элементов, которые анимируются предсказуемо и часто (например лента слайдера, которая движется почти постоянно), а не для случайного hover-эффекта на карточке, который срабатывает редко и без того легко анимируется.

Частые ошибки новичков

ОшибкаЧто происходитКак исправить
Добавлять will-change на много элементов "про запас", без реальной проблемы с производительностью Каждый элемент занимает отдельный композитный слой в памяти - суммарно может замедлить страницу вместо ускорения Использовать will-change как последнее средство для уже обнаруженной проблемы, а не заранее
Вешать will-change на простой одиночный hover-эффект с transform или opacity Эти свойства и так легко анимируются сами по себе (composite-only) - лишний слой не даёт заметного выигрыша Не добавлять will-change туда, где transform/opacity и без того плавные
Не знать, что will-change создаёт новый контекст наложения Дочерние элементы с отрицательным z-index неожиданно перестают "проваливаться" под соседей, визуальный порядок меняется Учитывать, что will-change (как и реальный transform) создаёт stacking context, и проверять z-index потомков
Держать will-change в таблице стилей постоянно для элементов, которые анимируются редко Слой занимает память всё время работы страницы, а не только во время самой анимации Постоянно в CSS оставлять только для предсказуемо и часто анимируемых элементов (например ленты слайдера)

Шпаргалка

ЗаписьЧто означает
will-change: autoЗначение по умолчанию - никакой подсказки браузеру
will-change: transform, opacityПодсказка подготовить слой заранее для этих свойств
will-change: scroll-position / contentsДля прокручиваемых контейнеров / часто меняющегося содержимого
will-change создаёт stacking contextМеняет поведение z-index у потомков, как и настоящий transform
"Последнее средство, не предугадывание"Главное правило MDN - применять только при реальной проблеме

Коротко: отвечаем на вопросы

Что именно делает will-change?

will-change подсказывает браузеру заранее, какое CSS-свойство элемента скоро изменится, чтобы браузер продвинул элемент в отдельный композитный слой ДО начала анимации, а не тратил время на подготовку слоя уже во время неё. Значения - auto (по умолчанию, без подсказки), имя свойства вроде transform или opacity, scroll-position для прокручиваемых контейнеров, contents для часто меняющегося содержимого.

Правда ли, что will-change можно вешать на любой анимируемый элемент "про запас"?

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

Как will-change влияет на z-index и порядок наложения элементов?

will-change создаёт у элемента собственный контекст наложения (stacking context), в точности как это сделал бы настоящий transform. Собственная проверка (сравнение пикселя в точке перекрытия двух блоков) показала: дочерний элемент с z-index: -1, который без will-change у родителя мог "провалиться" ниже соседнего элемента того же уровня, после добавления will-change: transform родителю больше не может этого сделать - он остаётся привязан к локальному контексту наложения родителя, и видимый порядок наложения реально меняется.

Когда всё-таки стоит использовать will-change без JavaScript?

"Золотой стандарт" - включать will-change через JavaScript непосредственно перед анимацией и выключать сразу после неё, что выходит за рамки этого курса. Практичный компромисс без JS - держать will-change прямо в таблице стилей только для элементов, которые анимируются предсказуемо и часто (например лента слайдера, движущаяся почти постоянно), а не для редкого hover-эффекта на карточке, который и без того легко анимируется на transform.

Категория
Поделиться в социальных сетях
1. Переходы: transition
2. Трансформации: transform
3. Ключевые кадры и animation
4. Фильтры: filter
5. Практика: живые интерфейсы
6. Производительность и доступность

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×