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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

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

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.