Как работает свойство interpolate-size в CSS и почему оно позволяет плавно анимировать переход к height: auto.
Анимация height: auto через interpolate-size
Долгое времяheight: autoсчиталось «неанимируемым»: браузер знал начальное значение, но не мог вычислить промежуточные между фиксированной длиной и высотой, зависящей от содержимого. Свойствоinterpolate-sizeснимает это ограничение.
Анимация высоты контейнера — один из самых частых приёмов в интерфейсах: раскрывающиеся карточки, аккордеоны, выпадающие панели. До недавнего времени разработчики обходили ограничение через max-height с заведомо большим значением, через измерение высоты в JavaScript или через сторонние библиотеки. Все эти подходы имели побочные эффекты: неточную длительность перехода, лишние вычисления в рантайме или усложнение разметки.
Свойство interpolate-size переносит решение задачи на уровень CSS. Оно сообщает браузеру, что размеры можно интерполировать не только между числовыми значениями, но и между числом и ключевым словом вроде auto, min-content или fit-content.
Проблема, которую решает свойство
По умолчанию браузер интерполирует только числовые значения: 0px → 200px, 1rem → 2rem. Ключевые слова не имеют числового представления до момента вычисления стилей, поэтому переход height: 0 → height: auto раньше просто не анимировался: значение менялось скачком.
Свойство interpolate-size разрешает браузеру вычислить внутренний размер элемента в момент перехода и построить плавную кривую между начальным числом и этим вычисленным размером.
/* Без interpolate-size переход мгновенный */
.card {
height: 0;
transition: height 0.4s;
}
.card:hover {
height: auto; /* значение применится скачком */
}
Синтаксис и значения
Свойство наследуется, поэтому его удобно задавать на :root. Оно принимает два значения.
numeric-only— значение по умолчанию. Интерполируются только числовые длины и проценты.allow-keywords— разрешает интерполяцию между длиной и внутренним размером (auto,min-content,max-content,fit-content).
:root {
interpolate-size: allow-keywords;
}
Поскольку свойство наследуемое, установка на корневом элементе распространяет поведение на весь документ. При необходимости можно переопределить его на отдельном поддереве.
Базовый пример: раскрывающаяся карточка
Классический сценарий — карточка, которая увеличивает высоту при наведении. Раньше приходилось задавать max-height с запасом, из-за чего переход завершался раньше, чем заканчивалась видимая анимация.
:root {
interpolate-size: allow-keywords;
}
.card {
height: 30px;
overflow: hidden;
transition: height 0.4s ease;
background: #f0f0f0;
border: 1px solid #ccc;
padding: 8px;
}
.card:hover {
height: auto;
}
В момент наведения браузер измеряет фактическую высоту содержимого и плавно переходит к ней. Длительность 0.4s относится ко всему переходу, а не к условному max-height.
Анимация к другим внутренним размерам
Свойство работает не только с auto. Оно поддерживает переходы к min-content, max-content и fit-content. Это полезно, когда нужно раскрыть элемент ровно под содержимое или, наоборот, ограничить его минимально возможной шириной.
:root {
interpolate-size: allow-keywords;
}
.panel {
width: 100px;
transition: width 0.3s ease;
}
.panel:hover {
width: fit-content;
}
В этом примере ширина плавно меняется от фиксированных 100px до размера, который определяется содержимым панели.
interpolate-size управляет не конкретным свойством, а правилом интерполяции для всего документа. Это глобальная настройка поведения анимации, а не локальный модификатор.
Ограничения и тонкости
Не всякая комбинация ключевых слов анимируется. Спецификация допускает интерполяцию между длиной и внутренним размером, но не между двумя разными внутренними размерами. Переход min-content → max-content останется мгновенным, поскольку оба значения являются ключевыми словами.
Также стоит учитывать, что интерполяция к auto требует вычисления внутреннего размера на каждом кадре анимации. Для сложных многоуровневых структур это может сказаться на производительности, поэтому злоупотреблять таким переходом в больших списках не стоит.
Связь с calc-size()
Функция calc-size() решает смежную задачу: она позволяет выполнять математические операции над внутренними размерами, например calc-size(auto, size + 20px). В отличие от interpolate-size, она включается не глобально, а локально в конкретном свойстве и автоматически разрешает интерполяцию для этого значения.
.card {
height: 30px;
transition: height 0.4s ease;
}
.card:hover {
height: calc-size(auto, size + 20px);
}
Выбор между двумя инструментами прост: если нужна только плавная анимация к auto, достаточно interpolate-size. Если же над внутренним размером требуется арифметика, применяется calc-size().
Что запомнить
interpolate-sizeразрешает анимацию между числовыми длинами и ключевыми словами размеров.- По умолчанию действует
numeric-only; для анимации кautoнужноallow-keywords. - Свойство наследуется и обычно задаётся на
:root. - Поддерживаются переходы к
auto,min-content,max-content,fit-content. - Переход между двумя ключевыми словами не интерполируется.
- Анимация к
autoвычисляет внутренний размер на каждом кадре — учитывайте это в тяжёлых структурах. - Для арифметики над внутренним размером используйте
calc-size(). - Оба инструмента устраняют потребность в трюке с
max-heightи в измерении высоты через JavaScript.