<div id="app">
  <ul>
    <li @click="toggle">toggle</li>

    <transition name="slide" @enter="setMaxHeight">
      <ul class="child" v-if="show">
        <li>item 1</li>
        <li>item 2</li>
        <li>item 3</li>
        <li>item 4</li>
      </ul>
    </transition>
  </ul>
</div>




ul {
  cursor: pointer;
}

.slide-enter-active {
  transition: 0.3s max-height ease-in;
}

.slide-leave-active {
  transition: 0.3s max-height cubic-bezier(0, 1, 0.5, 1);
}

.slide-enter-to, .slide-leave-from {
  max-height: var(--max-height, 1000px);
  overflow: hidden;
}

.slide-enter-from, .slide-leave-to {
  overflow: hidden;
  max-height: 0;
}
const { createApp, ref } = Vue;

createApp({
  setup() {
    const show = ref(false);
    const toggle = () => {
      show.value = !show.value;
    };
    const setMaxHeight = (el) => {
      el.style.setProperty(
        '--max-height',
        el.scrollHeight + 'px'
      );
    }
    return {
      show,
      toggle,
      setMaxHeight
    }
  }
}).mount('#app')

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://unpkg.com/vue@3