Going from 0 to Auto and from auto to 0 in CSS Transition is a difficult task (compared to other transitions) for a simple reason: browsers don’t support this kind of CSS animation, and it won’t work under any circumstances.

But height gradient is a very common animation effect. If you bypass the pure CSS height property, you can do it in the following ways:

  • usemax-heightProperty, sets the element to a maximum height that is impossible to reach, and then converts the transition tomax-heightFrom zero to some fixed value;
  • usetransform: scaleYImplementation;
  • Use JavaScript animation.

The above solutions all solve the problem to some extent, but each has its limitations and disadvantages:

  • usemax-heightWill cause the animation to be slightly different than expected (speed up and delay), but the actual experience is that it is notheightThe bigger the difference, the more obvious it will be, and it’s easy to imagine why, because the transition doesn’t start and end at the actual beginning and end.
  • usescaleYThere are two problems: first, unlike height gradients, the content of an element appears to be compressed (rather than folded or expanded), which is tolerable. The second thing is, it looks like it’s tweaked, but the height isn’t tweaked! This means that the element below it will “jump” to another position after the animation ends instead of smoothly transitioning to this position;
  • Height gradients are already perfectly possible using JavaScript animations, however, the problem is that we need to introduce extra lib to do this, and I’m not in the mood for purely js hand-written animations.

So, my goal is to:

  1. Use CSS Transition to animate.
  2. The animation must be perfect;
  3. Integration with the Vue Transition component.

This is actually a very difficult task. After r a lot of failed attempts, Google saved my life. Let’s go straight to the solution.

The CSS part is very simple, because it can’t do the tween from 0 to auto, but it can do the tween from 0 to a fixed value, so the idea is that the tween is still done by THE CSS, but the hook does some magic to the element:

.collapse {
  transition: height .3s ease-in-out;
  overflow: hidden;
}
Copy the code

Here’s the vue transition section:

on: {
  enter (el) {
    el.style.height = 'auto'
    // noinspection JSSuspiciousNameCombination
    let endWidth = window.getComputedStyle(el).height
    el.style.height = '0px'
    el.offsetHeight // force repaint
    // noinspection JSSuspiciousNameCombination
    el.style.height = endWidth
  },
  afterEnter (el) {
    el.style.height = null
  },
  leave (el) {
    el.style.height = window.getComputedStyle(el).height
    el.offsetHeight // force repaint
    el.style.height = '0px'
  },
  afterLeave (el) {
    el.style.height = null}}Copy the code

The hooks would look something like this:

  • enterIt fires when the element is created from scratch, when we expect the height to go from 0 to auto;
  • afterEnterWill be inenterTrigger after the end;
  • leaveEmitted when the element goes from presence to absence, i.e. height from auto to 0;
  • afterLeaveIn the same way

The code inside these hooks is really diabolical, and it looks something like this:

enter

When this method is called, the element is actually inserted into the DOM (v-if) or the display attribute is not None (v-show), so it is possible to get its actual height.

  1. Set its height toautoAnd then throughgetComputedStyleMethod to obtain its actual height;
  2. Set its height to0;
  3. Set its height to the actual height obtained in the first step.

But! The fatal problem with this is that I am doing all of these steps synchronously within the same method, so it looks like the second and third steps have been skipped and only the third step has been executed, so there is no height from zero to some value, and of course there is no gradient animation.

The point!

The magic here is actually the one that seems to do nothingel.offsetHeight, which forces the browser to enter a repaint process. I’m not quite sure why it does this, Google Wave just doesn’t know why, we don’t even have to assign a value to it, just reference it once. It’s a pretty amazing technique. The test works on IE 10 or above, Chrome, Firefox, or Safari.

Therefore, the flow for Enter becomes:

  1. Set its height toautoAnd then throughgetComputedStyleMethod to obtain its actual height;
  2. Set its height to0;
  3. Force browser redraw;
  4. Set its height to the actual height obtained in the first step.

Then the animation executes successfully!

After you understand the Enter process, the afterEnter/leave/afterLeave hooks are easy to understand.

Effect: demonstration uiv. WXSM. Space/components /…

The implementation is pretty straightforward, so you can use CSS Transition in other frameworks (such as ngAnimate in Angular) to animate perfectly. And without the help of any additional JS libraries outside of the main framework.