1

I have the following css:

    @keyframes expandTop {
      from {
        height: 0;
      }
      to {
        height: 100px;
      }
    }
    &.expand {
      animation: expandTop 0.5s ease-out forwards;
    }
    @keyframes collapseTop {
      from {
        height: 100px;
      }
      to {
        height: 0;
      }
    }
    &.collapse {
      animation: collapseTop 0.5s ease-out forwards;
    }
    &.still {
      animation: none;
    }
  }

This works but it feels like there should be a way to reuse the same @keyframes. I tried a bunch of combinations of reverse and backwards etc.. but to no avail. The animation is triggered by switching css class. I'd like something along those lines but that works:

    @keyframes top {
      from {
        height: 0;
      }
      to {
        height: 100px;
      }
    }
    &.expand {
      animation: top 0.5s ease-out forwards;
    }
    &.collapse {
      animation: top 0.5s ease-out reverse backwards;
    }
    &.still {
      animation: none;
    }

I've been banging my head on the docs but that's not helping... Am I screwed because I am using classes to trigger?

2 Answers 2

3

This is a job for transition not for animation

function e() {
  document.getElementById('div').classList.toggle('collapse');
  document.getElementById('div').classList.toggle('expand');
}
.still {
  transition: height 1s;
  background: red;
}

.collapse {
  height: 0;
}

.expand {
  height: 100px;
}
<button onclick="e()">switch</button>

<div id="div" class="collapse still"></div>

Sign up to request clarification or add additional context in comments.

Comments

1

You can reuse the same @keyframe animation for both expanding and collapsing by using animation-direction: reverse - no need for separate keyframes!

Just set the starting height correctly for collapse and let CSS handle the rest. The animation-fill-mode: forwards ensures the element stays in its final state after the animation completes.

The demo shows it in action (with JS), but the technique itself is pure CSS.

function expand() {
  const box = document.getElementById('demo');
  box.classList.remove('collapse');
  void box.offsetWidth;
  box.classList.add('expand');
}

function collapse() {
  const box = document.getElementById('demo');
  box.classList.remove('expand');
  void box.offsetWidth;
  box.classList.add('collapse');
}
.box {
  width: 100px;
  background: #3498db;
  overflow: hidden;
  height: 0;
}

@keyframes top {
  from {
    height: 0;
  }

  to {
    height: 100px;
  }
}

.expand {
  animation-name: top;
  animation-duration: 1s;
  animation-timing-function: ease-out;
  animation-fill-mode: forwards;
}

.collapse {
  /* Initial height needed for reverse animation */
  height: 100px;
  animation-name: top;
  animation-duration: 1s;
  animation-timing-function: ease-out;
  animation-fill-mode: forwards;
  animation-direction: reverse;
}
<div>
  <button onclick="expand()">Expand</button>
  <button onclick="collapse()">Collapse</button>
</div>
<div id="demo" class="box"></div>

2 Comments

Excuse me, this code snipped does not show anything. Did you test it in this page? As a minimum, you need HTML part as well.
Sorry, was trying to move the javascript to the last, since it's not really the main part here, but the snippet won't allow that =)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.