Implementing a Smooth Collapsible Panel (Accordion) in Vue Without Third‑Party UI Libraries
This article demonstrates how to build a responsive, animated collapsible side‑menu panel in Vue by using plain HTML, CSS transitions, Vue's transition component, dynamic class bindings, and a few lines of JavaScript to control height, offering a lightweight alternative to third‑party UI libraries.
The requirement is to create a left‑sidebar menu that expands and collapses with a smooth animation, essentially a "collapsible panel". Since third‑party component libraries cannot be used, the solution is built from scratch using Vue 3.
Basic Structure
<template>
<div class="nav-bar-content">
<div class="header-wrap" @click="open = !open">
<span class="text">自动化需求计算条件输如</span>
<span class="arrow">></span>
</div>
<div v-show="open" class="content">
<p>算法及跃变计算条件</p>
<p>空间品质判断条件</p>
<p>需求自动计算条件</p>
<p>通风系统</p>
</div>
</div>
</template>
<script setup>
const open = ref(false);
</script>Clicking the header toggles the open variable, which controls the visibility of the content area via v-show .
Arrow Rotation Animation
<style lang="less" scoped>
.arrow {
width: 16px;
height: 16px;
cursor: pointer;
margin-left: 1px;
transition: transform 0.2s ease;
}
.open {
transform: rotate(90deg);
transition: transform 0.2s ease;
}
</style>The arrow receives the open class when the panel is expanded, rotating it 90° with a CSS transition.
Collapsible Area Animation Using Vue's Transition Component
<template>
<div class="nav-bar-content">
<div class="header-wrap" @click="open = !open">
<span class="text">自动化需求计算条件输如</span>
<span class="arrow" :class="{ open: open }">></span>
</div>
<div class="content-wrap">
<Transition>
<div v-show="open" class="content">
...
</div>
</Transition>
</div>
</div>
</template>
<style lang="less" scoped>
.v-enter-active, .v-leave-active { transition: transform 0.5s ease; }
.v-enter-from, .v-leave-to { transform: translateY(-100%); }
</style>This makes the panel slide in from the top while fading, using Vue's built‑in transition classes.
Dynamic Height Animation (CSS‑Only)
<style lang="less" scoped>
.content-wrap {
overflow: hidden;
height: 0;
transition: height 0.5s ease;
}
</style>By binding the height style to open ? '300px' : 0 , the panel expands smoothly without JavaScript calculations.
Dynamic Height with JavaScript for Variable Content
<script setup>
const open = ref(false);
const contentRef = ref();
const height = ref('0');
onMounted(() => {
height.value = contentRef.value.offsetHeight + 'px';
});
</script>
<template>
...
<div class="content-wrap" :style="{ height: open ? height : 0 }">
<div class="content" ref="contentRef">
<slot></slot>
</div>
</div>
</template>This approach measures the actual content height on mount and applies it when the panel opens, ensuring the animation works for dynamic slot content.
Conclusion
While using a third‑party UI library is the simplest way to obtain an accordion effect, the article shows that with a few lines of Vue template, CSS transitions, and optional JavaScript height calculation, developers can implement a lightweight, fully customizable collapsible panel suitable for projects that cannot depend on external component libraries.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.