Home > OS >  How can I animate by expanding/collapsing a div when adding an element
How can I animate by expanding/collapsing a div when adding an element

Time:06-07

I am making a To-do list where you can see the task's description when clicking on the task, basically I toggle the description's display from display: none; to display: block;, the problem is that when I make the description visible the parent div suddenly changes height and i want to animate it so that its smoother.

const tasks = document.querySelectorAll('.task')

tasks.forEach(x => {
  x.onclick = () => {
    x.querySelector('.description').classList.toggle('show')
    if (x.className == 'task flex') {
      x.className = 'task grid'
    } else {
      x.className = 'task flex'
    }
  }
})
* {
  font-family: poppins;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.project {
  background-color: teal;
  color: var(--white);
  display: grid;
  grid-template: 1fr 2fr / 1fr;
  border-radius: 10px;
}

.project * {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  height: 100%;
}

.project h3 {
  align-items: center;
  font-size: 1.5rem;
  font-weight: 500;
  margin-bottom: 1.5rem;
  color: #ffffff;
}

.tasks {
  align-items: flex-start;
  gap: 0.5rem;
  padding: 0 1rem 1rem;
}

.task {
  background-color: rgb(251, 238, 202);
  color: rgb(37, 36, 34);
  border-radius: 10px;
}

.flex {
  display: flex;
  flex-direction: row;
  align-items: center;
  padding: 0.5rem 0.5rem 0.5rem 0.75rem;
}

.grid {
  display: grid;
  grid-template: 1fr 1fr / 5fr 5fr 15px;
  grid-template-areas: none;
  padding: 0.5rem 0.5rem 0.5rem 0.75rem;
  grid-template-areas: 'task date del' 'desc desc desc';
}

.title {
  font-size: 18px;
  line-height: 25px;
  grid-area: task;
}

.description {
  display: none;
  color: rgba(0, 0, 0, 0.6);
  font-size: 1rem;
  margin-left: 0.5rem;
  grid-area: desc;
}

.show {
  transform: scaleY(1);
  transition: transform 1s ease 0ms;
  display: block;
}

.date {
  color: var(--main-dark);
  font-style: italic;
  text-align: right;
  padding-right: 1rem;
  grid-area: date;
}
<div >
  <h3>Default project</h3>
  <div >
    <div >
      <p >Water the plants</p>
      <p >Tulips and Roses</p>
      <p >18 Jun 2022</p>
    </div>
    <div >
      <p >Feed the dog</p>
      <p >Chicken breast and bone</p>
      <p >18 Jun 2022</p>
    </div>
    <div >
      <p >Do the dishes</p>
      <p >From lunch</p>
      <p >18 Jun 2022</p>
    </div>
  </div>
</div>

CodePudding user response:

My standard for collapsing content vertically is the max-height property.

In theory, its pretty simple.

You have an element of max-height: 0px; and an active state of max-height: 300px;. Then you can add a transition like this: transition: max-height 0.5s ease; and it will work. However, there is a catch doing this with pure CSS.

EDIT// Remember to give your collapsing content a overflow: hidden;

Imagine your content is user submitted like in your case. The description could be 200px, 500px or even 0px of height.

In the case of your content being 300px, everything will work and animate like a charm because you perfectly hit the limit you defined.

In the case of your content being smaller, for example 200px, the animation will differ because it is still animating from 0px to 300px. Your content stops expanding at 200px so it will be faster than expanded than the 300px element. In fact, collapsing the element back to 0px will result in a delay of about 1/3 of your animation time because the element will stay at 200px until the transition has gone from 300px to 200px. Only then it will start collapsing.

Of course, there is always the option to just not bother and set the max-height to a reasonable default for your use-case.

As long as I've known AlpineJS, a minimal JS framework which is very easy to use, I didn't have to bother with this because the Collapse Plugin will do all the JS calculation for me so that the content is always transitioning perfectly. AlpineJS Collapse

If you don't want to use a JS Framework for this, there is a simple explanation on how to calculate the height of the element using JS, you can take a look at it here: W3Schools Collapsible

I can only reccommend taking a look at it or live with the consequences of the hard-coded default 300px or so.

CodePudding user response:

Here is how I animate, where max-height is any hight that surpasses the max height of the element, if you have min height you can specify it too

#elementThatWillExpand
{
min-height:10px;
max-height:2000px;
transition:height 2s;
overflow:hidden;
}

So this should work, just change

.show {
  transform: scaleY(1);
  transition: transform 1s ease 0ms;
  display: block;
}

To

.show {
  display: block;
  max-height:3000px;
  transition:height 1s;
  overflow:hidden;
}
  • Related