Как анимировать высоту до auto
Короткий ответ
Разрешите анимацию к ключевым словам вроде auto одной строкой на :root:
<style>
:root { interpolate-size: allow-keywords; }
.panel { height: 0; overflow: hidden; transition: height 0.4s; background: lavender; }
label:has(:checked) + .panel { height: auto; }
</style>
<label><input type="checkbox"> Show details</label>
<div class="panel">
<p>Delivery takes 2–3 days. Returns are free within 30 days.</p>
</div>Раньше transition не умел анимировать height: auto: блок раскрывался рывком. interpolate-size: allow-keywords разрешает плавный переход между числом и auto, min-content, fit-content. Свойство наследуется, поэтому достаточно задать его один раз на :root.
Только для одного свойства
Если не хотите включать это для всей страницы, используйте функцию calc-size() прямо в значении: height: calc-size(auto, size);. Результат тот же, но только у этого правила.
Запасной приём для всех браузеров
interpolate-size есть не во всех браузерах — там блок откроется без анимации. Приём с сеткой работает везде: анимируется высота строки от 0fr до 1fr, а 1fr и есть высота содержимого:
<style>
.wrap { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.4s; background: honeydew; }
.wrap > div { overflow: hidden; }
label:has(:checked) + .wrap { grid-template-rows: 1fr; }
</style>
<label><input type="checkbox"> Show details</label>
<div class="wrap">
<div><p>Delivery takes 2–3 days. Returns are free within 30 days.</p></div>
</div>Внутренний <div> с overflow: hidden обязателен: без него содержимое не сожмётся до нуля.
Частая ошибка
Анимировать max-height с запасом, например до 1000px. Переход идёт до тысячи пикселей, а содержимое занимает сто, поэтому раскрытие заканчивается почти мгновенно, а закрытие начинается с паузой. Используйте interpolate-size или приём с сеткой — они анимируют настоящую высоту.
Функции из этого ответа
- interpolate-size — Разрешает переходы к ключевым словам размера и от них — `auto`, `min-content`, `fit-content`. Наконец-то `height: 0` → `height: auto`.
- height — Высота элемента.
- transition — Плавно анимирует изменение свойства от старого значения к новому.
- grid-template-rows — Количество и высота рядов сетки.
- :has() — Выбирает элемент, внутри которого есть что-то подходящее под селектор в скобках, — «селектор родителя».