In this tutorial we’ll be using Alpine.js to build an accordion component. Accordions or collapsible panels as they’re also known are used to hide and show large amounts of content by clicking a heading. Please note, to keep this tutorial Alpine focused I’ve used the Tailwind CSS framework but it could easily be converted to plain CSS.
Let’s get started by creating a new HTML file and loading Alpine and Tailwind via CDN:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Alpine.js Accordion</title>
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet" />
<script src="https://unpkg.com/alpinejs" defer></script>
</head>
<body>
</body>
</html>
Code language: HTML, XML (xml)
Now for the accordion data which is stored in an array as follows:
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('accordion', () => ({
data: [
{
id: '1',
heading: 'What is Alpine.js?',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus quis pharetra dui, ac feugiat metus. Vivamus id pellentesque urna, quis hendrerit tortor. Sed pharetra sapien a metus fringilla varius.',
isOpen: false,
},
{
id: '2',
heading: 'Is Alpine.js better than jQuery?',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus quis pharetra dui, ac feugiat metus. Vivamus id pellentesque urna, quis hendrerit tortor. Sed pharetra sapien a metus fringilla varius.',
isOpen: false,
},
{
id: '3',
heading: 'Who created Alpine.js?',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus quis pharetra dui, ac feugiat metus. Vivamus id pellentesque urna, quis hendrerit tortor. Sed pharetra sapien a metus fringilla varius.',
isOpen: false,
},
]
}))
});
</script>
Code language: HTML, XML (xml)
The eventListener
here is waiting for Alpine to load before creating a data object.
Next we can start with the accordion component itself:
<div x-data="accordion" class="p-3"></div>
Code language: HTML, XML (xml)
Components in Alpine always have the x-data
directive which defines a section of HTML as an Alpine component. It also provides the reactive data for a component to reference, in our case the accordion
data created in the previous step.
We’ll use the <template>
element for holding the HTML as it isn’t be rendered immediately:
<div x-data="accordion" class="p-3">
<template x-for="accordion in data" :key="accordion.id"></template>
</div>
Code language: HTML, XML (xml)
Alpine’s x-for
directive iterates through the data to create the following markup:
<div x-data="accordion" class="p-3">
<template x-for="accordion in data" :key="accordion.id">
<div class="accordion">
<button @click="data = data.map(i => ({ ...i, isOpen: i.id !== accordion.id ? false : !i.isOpen}))"
class="w-full flex justify-between items-center border-b py-3">
<h3 x-text="accordion.heading" class="font-bold"></h3>
</button>
<div x-text="accordion.content" x-show="accordion.isOpen" class="py-3"></div>
</div>
</template>
</div>
Code language: HTML, XML (xml)
When the button is clicked the isOpen
value is toggled between true
and false
. The x-text
directive gets the accordion content and displays it within the element it reside. The final piece of Alpine used is x-show
which controls the visibility on and element so only when accordion.isOpen
equals true
is the content visible.
Finally let’s add an icon to indicate whether or not the accordion is open or closed:
<div class="accordion">
<button @click="data = data.map(i => ({ ...i, isOpen: i.id !== accordion.id ? false : !i.isOpen}))"
class="w-full flex justify-between items-center border-b py-3">
<h3 x-text="accordion.heading" class="font-bold"></h3>
<span x-show="accordion.isOpen">-</span>
<span x-show="!accordion.isOpen">+</span>
</button>
<div x-text="accordion.content" x-show="accordion.isOpen" class="py-3"></div>
</div>
Code language: HTML, XML (xml)
Once again we’ve used x-show
to control the visibility of the open and closed icons based on the value of accordion.isOpen
.
That’s all for this tutorial, you should now have a fully functioning accordion component powered by Alpine.js. If you enjoyed this tutorial you may also be interested in some of our other Apline.js tutorials.