Наверняка каждый опытный верстальщик сталкивался с вопросом: как анимировать изменение высоты блока с 0 до auto и наоборот. Это частая задача при разработке аккордеонов и других разворачивающихся при взаимодействии элементов.
В этой статье я рассмотрю три решения и приложу пример рабочего аккордеона, плавно меняющего высоту при наведении.
Демо
Первый абзац
Второй абзац
Третий абзац
Четвёртый абзац
Пятый абзац
Разметка
Начнём с HTML. Код для демонстрации следующий:
<div class="accordion">
<div class="accordion-title">Наведи на меня</div>
<div class="accordion-body">
<div>
<p>Текст внутри аккордеона</p>
</div>
</div>
</div>
Попытка №1 (тщетная)
Наверняка каждый пробовал просто добавить transition для свойства height:
.accordion-body {
height: 0;
transition: 500ms height ease;
}
.accordion:hover .accordion-body {
height: auto;
}
К сожалению, CSS не позволяет анимировать автоматически вычисляемую высоту, так как браузер в данном случае не знает точной высоты, до которой нужно увеличить элемент. Подробнее можно почитать в спецификации: https://drafts.csswg.org/web-animations-1/#the-animationeffect-interface («that simply means that an auto value is replaced by zero»)
Попытка №2 (не идеальная)
А что, если анимировать max-height?
.accordion-body {
max-height: 0;
transition: 500ms max-height ease;
}
.accordion:hover .accordion-body {
max-height: 200px;
}
Так как браузер знает конкретное значение свойства (max-height), то он сможет его анимировать.
Но есть проблема: контент может не уместиться в указанную высоту. Если этот нюанс не доставит неудобств, то это вполне приемлемый вариант анимирования высоты блока.
Попытка №3 (успешная)
Мы можем использовать изящный трюк, который заключается в создании грида с одним элементом сетки. Этот трюк работает только из-за анимируемости строк грида.
.accordion-body {
display: grid;
grid-template-rows: 0fr;
transition: 250ms grid-template-rows ease;
}
.accordion:hover .accordion-body {
grid-template-rows: 1fr;
}
.accordion-body > div {
overflow: hidden;
}
Нюанс: необходимо для div внутри .accordion-body установить overflow: hidden, чтобы сработало.
Учтите, что анимирование свойства grid-template-rows поддерживается не всеми браузерами: