Как стать автором
Обновить

CSS-переход свойства height от 0px до auto

Время на прочтение2 мин
Количество просмотров32K
Здравствуй, Хабр!

Хочу поделиться ещё одним способом создания css-перехода (transition) свойства height от 0px до auto.

Столкнулся с данной проблемой при разработке веб-компонентов TreeView и DataGrid. В TreeView решил сделать плавное развёртывание/свёртывание узлов, а в DataGrid — строки с дополнительным контентом. Почитав интернет, нашёл несколько способов реализации, основные — через свойство max-height и на javascript. Реализация на javascript была исключена — есть же css с поддержкой переходов и анимаций. Остался max-height, тем более в примерах с выпадающими меню всё работает.

В TreeView каждый узел имеет неограниченную вложенность, поэтому сразу не получится определить максимальную высоту его содержимого, да и если max-height задать очень большим, будут проблемы с анимацией перехода. Также, если развернуть дочерние узлы, высота родительского увеличится и может перекрыть max-height. Как ни крути, max-height не подходит. С DataGrid та же проблема — дополнительный контент в строке может быть любой. Нужен height:auto!

Итак, приступим к реализации перехода по свойству height от 0px до auto. Рассмотрим простой пример.

Пусть:

  • elBlock: HTMLDivElement — блок, который нужно развёртывать/свёртывать;
  • elToggle: HTMLButtonElement — кнопка-переключатель состояния.

Определим css-класс для блока, в котором установим обрезку содержимого и сам переход:

.block {
    overflow: hidden;
    transition: height 500ms ease;
}

Опишем обработчик события onClick для elToggle:

elToggle.addEventListener("click", () => {
    if (elBlock.style.height === "0px") {
        elBlock.style.height = `${ elBlock.scrollHeight }px`
    } else {
        elBlock.style.height = `${ elBlock.scrollHeight }px`;
        window.getComputedStyle(elBlock, null).getPropertyValue("height");
        elBlock.style.height = "0";
    }
});

Осталось добавить возврат height:auto после перехода:

elBlock.addEventListener("transitionend", () => {
    if (elBlock.style.height !== "0px") {
        elBlock.style.height = "auto"
    }
});

Ну вот и всё, теперь развёртывание/свёртывание блока работает как надо и не зависит от размера контента.


Рисунок 1 — Пример развёртывания/свёртывания узлов в TreeView

Стоит отметить минусы данного подхода:

  • использование javascript, хотелось бы только css;
  • во время перехода может измениться контент (его высота, scrollHeight) и после его завершения, в случае возврата auto, высота блока резко поменяется в ту или иную сторону. Для избежания данного эффекта, необходимо отслеживать изменение scrollHeight и менять height. Как показывает практика, обычно переходы развёртывания/свёртывания занимают по 0.5 с, а за это время пользователь вряд ли успеет изменить что-то внутри, например, в случае TreeView, развернуть дочерний узел.

Спасибо за внимание!
Теги:
Хабы:
Всего голосов 20: ↑14 и ↓6+8
Комментарии42

Публикации

Истории

Работа

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
10 – 11 октября
HR IT & Team Lead конференция «Битва за IT-таланты»
МоскваОнлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн