12 maj 2023

Jak animować wysokość od 0 do auto?

Mamy div który ma wysokość ustawioną na height: 0;. Po kliknięciu chcemy aby była "gładka" animacja pojawiąjącego się tekstu. Jest jeden problem, po toggle wysokość jest ustawiana na auto i zamiast "gładkiego" przejścia z wysokości 0 do auto, div po prostu się pojawia zamiast zwiększyć wysokość dynamicznie.
Powiesz, a czemu nie ustawić wysokości na konkretną "height i tutaj jest problem bo strona jest dynamiczna, więc wysokość tego diva z tekstem również jest dynamiczna.

Dobra najpierw pokażę jak to wygląda normalnie:

<button>Toggle</button>
<div class="expandable">
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio
  deserunt porro nostrum dignissimos eveniet aperiam harum! Illum et eos
  atque. Dolorem, dolor deleniti impedit quibusdam nobis numquam quae
  maiores itaque? Lorem ipsum dolor sit, amet consectetur adipisicing elit.
  Et harum, minus, odit impedit id soluta nostrum nemo repudiandae fugit
  voluptatum voluptatibus fugiat quas cupiditate necessitatibus sunt numquam
  adipisci libero, deserunt distinctio deleniti quo eligendi?
</div>

Oczywiście potrzebujemy również css:

.expandable {
  height: 0;
  overflow: hidden;
  background: black;
  color: white;
  transition: 200ms height ease-in-out;
}

.expandable.open {
  height: auto;
}

A także js:

const button = document.querySelector("button");
const expandable = document.querySelector(".expandable");

button.addEventListener("click", (e) => {
  expandable.classList.toggle("open");
});

A teraz wersja, która naprawia ten błąd.
Najważniejszą rzecz to musimy ten div owinąć w dodatkowy div.

<button>Toggle</button>
<div class="wrapper">
  <div class="expandable">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio
    deserunt porro nostrum dignissimos eveniet aperiam harum! Illum et eos
    atque. Dolorem, dolor deleniti impedit quibusdam nobis numquam quae
    maiores itaque? Lorem ipsum dolor sit, amet consectetur adipisicing
    elit. Et harum, minus, odit impedit id soluta nostrum nemo repudiandae
    fugit voluptatum voluptatibus fugiat quas cupiditate necessitatibus sunt
    numquam adipisci libero, deserunt distinctio deleniti quo eligendi?
  </div>
</div>

Musimy również zmodyfikować css

.expandable {
  min-height: 0;
  background: black;
  color: white;
}

.wrapper {
  max-width: 600px;
  display: grid;
  grid-template-rows: 0fr;
  overflow: hidden;
  transition: grid-template-rows 200ms;
}

.wrapper.open {
  grid-template-rows: 1fr;
}

I lekko również zmodyfikować, js. Zamiast dodać klasę open do klasy expandable dodajmy ją do naszego wrappera.

const button = document.querySelector("button");
const wrapper = document.querySelector(".wrapper");

button.addEventListener("click", (e) => {
  wrapper.classList.toggle("open");
});