Frontend Development 10 min read

Vue Expand/Collapse Animation for FAQ Section

The article shows how to create a smooth FAQ expand‑collapse effect in Vue by storing each item’s visibility in a show flag, wrapping the answer in a transition component, and using JavaScript hooks to set explicit heights and overflow while rotating the arrow icon for visual feedback.

HelloTech
HelloTech
HelloTech
Vue Expand/Collapse Animation for FAQ Section

In many mobile apps a FAQ (question‑answer) module is required. The static page is simple, but the expand/collapse effect for the answer part can be tricky because the answer container’s height is determined by its inner content (height: auto), which makes CSS height transitions ineffective.

The solution is demonstrated with Vue. First, the data structure is defined (using TypeScript syntax for clarity):

interface QaItem {
  Q: string; // question
  A: string; // answer
  show: boolean; // whether the answer is displayed
}

type QaList = QaItem[];

The corresponding Vue template (simplified) looks like this:

<div class="qa panel">
  <div class="qa__title">Common Questions</div>
  <div class="list-qa">
    <div v-for="(item, ind) in qaList" :key="ind" class="list-qa__item">
      <div class="list-qa__question">
        <span>{{ item.Q }}</span>
        <span class="list-qa__question__arrow" />
      </div>
      <span class="list-qa__answer" v-show="item.show">{{ item.A }}</span>
    </div>
  </div>
</div>

The answer visibility is controlled by the show property and rendered with v-show . For the expand/collapse animation, Vue’s transition component is used together with JavaScript hook functions that explicitly set the element’s height.

<transition
  name="slide"
  @before-enter="beforeEnter"
  @enter="enter"
  @after-enter="afterEnter"
  @before-leave="beforeLeave"
  @leave="leave"
  @after-leave="afterLeave"
>
  <span v-show="item.show" class="list-qa__answer">{{ item.A }}</span>
</transition>

JavaScript hook implementations:

beforeEnter(el) {
  el.style.transition = '0.3s height ease-in-out';
  el.style.overflow = 'hidden';
},
enter(el) {
  el.style.height = 'auto';
  const endHeight = window.getComputedStyle(el).height;
  el.style.height = '0px';
  el.offsetHeight; // force reflow
  el.style.height = endHeight;
},
afterEnter(el) {
  el.style.transition = '';
  el.style.overflow = 'visible';
},

beforeLeave(el) {
  el.style.transition = '0.3s height ease-in-out';
  el.style.overflow = 'hidden';
},
leave(el) {
  el.style.height = window.getComputedStyle(el).height;
  el.offsetHeight; // force reflow
  el.style.height = '0px';
},
afterLeave(el) {
  el.style.transition = '';
  el.style.overflow = 'visible';
}

The arrow rotation effect is achieved with a simple CSS transition. When the arrow is clicked, a class is toggled to rotate the icon 180 degrees:

<span class="list-qa__question__arrow"
      :class="{'list-qa__question__rotate-arrow': !item.show}"
      @click="onClickProblem(ind)" />
onClickProblem(index) {
  const qaItem = this.qaList[index];
  this.$set(qaItem, 'show', !qaItem.show);
}

Corresponding CSS:

.list-qa__question__arrow {
  width: 12px;
  height: 12px;
  background: url(https://m.hellobike.com/resource/helloyun/21588/RIBiB_SketchPngf4c3c2445f4522fe182c1d02d45a6201fa03ecfb14550a3269204012abdcfa09) center no-repeat;
  transition: transform .4s;
}
.list-qa__question__rotate-arrow {
  transform: rotateZ(180deg);
  transition: transform .4s;
}

By explicitly setting the element’s height from 0 to the computed pixel value (and vice‑versa) and using overflow: hidden , the desired smooth expand/collapse animation is achieved, while the arrow rotation provides a visual cue for the user.

This tutorial demonstrates the principle of CSS transitions, the limitation of transitioning to/from auto , and a practical Vue‑based workaround.

Front-endJavaScriptVueCSS TransitionExpand CollapseFAQ
HelloTech
Written by

HelloTech

Official Hello technology account, sharing tech insights and developments.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.