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-iforv-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-ifwithout 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-expandedand 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
refto create reactive state for open section. - Toggle open section with a function triggered by
@click. - Use
v-showorv-ifto conditionally display content. - Add accessibility attributes like
aria-expandedandrole="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.