#AD Top Online Web Development & Programming Courses | Udemy
Newsletter Screenshot

Build an accordion component with Alpine.js

Last modified December 1st 2021 | GitHub Source Code [GitHub] | #alpine

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.

Related Posts

#AD Shop Web Developer T-Shirts