0
0
VueHow-ToBeginner · 4 min read

How to Create Accordion in Vue: Simple Example and Syntax

To create an accordion in Vue, use a reactive state variable to track which section is open and toggle it on click with v-if or v-show. Use Vue's template syntax to bind click events and conditionally render the content inside each accordion item.
📐

Syntax

An accordion in Vue typically uses a reactive variable to track the open section. Use @click to toggle the state and v-if or v-show to conditionally display content.

Example parts:

  • data(): holds the open section index or id.
  • @click: toggles the open section.
  • v-if or v-show: shows or hides content.
vue
<template>
  <div>
    <div @click="toggle(1)">Section 1</div>
    <div v-if="open === 1">Content 1</div>

    <div @click="toggle(2)">Section 2</div>
    <div v-if="open === 2">Content 2</div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const open = ref(null)
function toggle(id) {
  open.value = open.value === id ? null : id
}
</script>
Output
Two clickable headers labeled 'Section 1' and 'Section 2'. Clicking a header shows its content below it, hiding the other if open.
💻

Example

This example shows a simple accordion with three sections. Clicking a section header toggles its content. Only one section can be open at a time.

vue
<template>
  <div class="accordion">
    <div class="item" v-for="section in sections" :key="section.id">
      <button
        class="header"
        @click="toggle(section.id)"
        :aria-expanded="open === section.id"
        :aria-controls="`content-${section.id}`"
        :id="`header-${section.id}`"
      >
        {{ section.title }}
      </button>
      <div
        v-show="open === section.id"
        class="content"
        :id="`content-${section.id}`"
        :aria-labelledby="`header-${section.id}`"
        role="region"
      >
        {{ section.content }}
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const sections = [
  { id: 1, title: 'Section 1', content: 'Content for section 1.' },
  { id: 2, title: 'Section 2', content: 'Content for section 2.' },
  { id: 3, title: 'Section 3', content: 'Content for section 3.' }
]

const open = ref(null)

function toggle(id) {
  open.value = open.value === id ? null : id
}
</script>

<style scoped>
.accordion {
  max-width: 400px;
  margin: 1rem auto;
  border: 1px solid #ccc;
  border-radius: 4px;
}
.item + .item {
  border-top: 1px solid #ccc;
}
.header {
  width: 100%;
  text-align: left;
  padding: 1rem;
  background: #f7f7f7;
  border: none;
  cursor: pointer;
  font-weight: bold;
}
.content {
  padding: 1rem;
  background: white;
}
</style>
Output
A vertical list of three headers labeled 'Section 1', 'Section 2', and 'Section 3'. Clicking a header reveals its content below with a white background, hiding others.
⚠️

Common Pitfalls

Common mistakes when creating accordions in Vue include:

  • Not using a reactive variable to track open sections, so UI does not update.
  • Using v-if without keys in loops, causing rendering issues.
  • Not toggling the open section properly, so multiple sections stay open or none toggle.
  • Ignoring accessibility attributes like aria-expanded and roles.
vue
<!-- Wrong: open is not reactive, so UI won't update -->
<script setup>
let open = null
function toggle(id) {
  open = open === id ? null : id
}
</script>

<!-- Right: use ref for reactivity -->
<script setup>
import { ref } from 'vue'
const open = ref(null)
function toggle(id) {
  open.value = open.value === id ? null : id
}
</script>
📊

Quick Reference

  • Use ref to create reactive state for open section.
  • Toggle open section with a function triggered by @click.
  • Use v-show or v-if to conditionally display content.
  • Add accessibility attributes like aria-expanded and role="region".
  • Style headers as buttons for keyboard navigation.

Key Takeaways

Use Vue's reactive ref to track which accordion section is open.
Toggle the open section on header click using a simple function.
Show or hide content with v-if or v-show for smooth UI updates.
Add accessibility attributes like aria-expanded and role="region" for better usability.
Style accordion headers as buttons to support keyboard navigation.