Vue.js custom accordion and easily customizable. without any npm plugin and without jquery.
Components 1: Slot.vue
Create an Slot.vue file located in the src/components/Accordion folder, and add the following components of code to the file.
<template> <ul class="accordion"> <slot></slot> </ul> </template> <script> export default { name: 'Accordion', props: {}, data() { return { Accordion: { count: 0, active: null } }; }, provide() { return { Accordion: this.Accordion }; } } </script>
Components 2: AccordionItem.vue
Create an AccordionItem.vue file located in the src/components/Accordion folder, and add the following components of code to the file.
<template> <li class="accordion__item"> <div class="accordion__trigger" :class="{'accordion__trigger_active': visible}" @click="open" > <slot name="accordion-trigger"></slot> </div> <transition name="accordion" @enter="start" @after-enter="end" @before-leave="start" @after-leave="end" > <div class="accordion__content" v-show="visible" > <ul> <slot name="accordion-content"></slot> </ul> </div> </transition> </li> </template> <script> export default { name: 'AccordionItem', props: {}, inject: ["Accordion"], data() { return { index: null }; }, computed: { visible() { return this.index == this.Accordion.active; } }, methods: { open() { if (this.visible) { this.Accordion.active = null; } else { this.Accordion.active = this.index; } }, start(el) { el.style.height = el.scrollHeight + "px"; }, end(el) { el.style.height = ""; } }, created() { this.index = this.Accordion.count++; } } </script>
Components 3: Accordion.vue
Create an Accordion.vue file located in the src/components/Accordion folder, and add the following components of code to the file.
<template> <div class="faq-area ptb-100"> <div class="container"> <div class="section-title"> <span>FAQ</span> <h2>Frequently Ask Questions</h2> </div> <div class="faq-accordion"> <accordion> <accordion-item> <template v-slot:accordion-trigger> <button class="accordion-button"> Why Are Consultants Important? </button> </template> <template v-slot:accordion-content> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Est nibh felis tortor viverra pulvinar nibh tincidunt pellentesque dolor. Sem lectus magna metus sit felis, ipsum, et. Auctor tellus id nunc nibh felis aliquam.</p> </template> </accordion-item> <accordion-item> <template v-slot:accordion-trigger> <button class="accordion-button"> What is The Purpose of a Consultant? </button> </template> <template v-slot:accordion-content> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Est nibh felis tortor viverra pulvinar nibh tincidunt pellentesque dolor. Sem lectus magna metus sit felis, ipsum, et. Auctor tellus id nunc nibh felis aliquam.</p> </template> </accordion-item> <accordion-item> <template v-slot:accordion-trigger> <button class="accordion-button"> What Attracts You To The Role of a Consultant? </button> </template> <template v-slot:accordion-content> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Est nibh felis tortor viverra pulvinar nibh tincidunt pellentesque dolor. Sem lectus magna metus sit felis, ipsum, et. Auctor tellus id nunc nibh felis aliquam.</p> </template> </accordion-item> <accordion-item> <template v-slot:accordion-trigger> <button class="accordion-button"> What Are The Advantages of Being a Consultant? </button> </template> <template v-slot:accordion-content> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Est nibh felis tortor viverra pulvinar nibh tincidunt pellentesque dolor. Sem lectus magna metus sit felis, ipsum, et. Auctor tellus id nunc nibh felis aliquam.</p> </template> </accordion-item> </accordion> </div> </div> </div> </template> <script> import Accordion from "./Slot"; import AccordionItem from "./AccordionItem"; export default { name: 'Faq', components: { Accordion, AccordionItem } } </script> <style lang="scss"> .faq-accordion { max-width: 1050px; margin: auto; .accordion { padding-left: 0; list-style-type: none; .accordion__item { border: 1px solid #E5E5E5; margin-bottom: 15px; transition: var(--transition); border-radius: 5px; &:last-child { margin-bottom: 0; } .accordion__trigger { .accordion-button { color: var(--black-color); position: relative; text-align: start; box-shadow: unset; margin-bottom: 0; display: block; border: none; width: 100%; font-size: 18px; font-weight: bold; padding: 20px 55px 20px 25px; transition: var(--transition); background-color: transparent; font-family: var(--heading-font-family); &::before { position: absolute; right: 20px; top: 18px; content: "+"; // content: "\EA4E"; // font-family: 'remixicon'; font-size: 20px; color: var(--black-color); } } &.accordion__trigger_active { .accordion-button { &::before { content: "-"; color: var(--main-color); } } } } .accordion__content { padding: 0 25px 20px; border-bottom: 5px solid var(--main-color); transition: var(--transition); border-radius: 0 0 5px 5px; ul { padding-left: 0; } p { color: var(--paragraph-color); font-size: 15px; } } &:hover { border-radius: 5px; border: 1px solid var(--main-color); .accordion__trigger { .accordion-button { &::before { color: var(--main-color); } } } .accordion-body { border-radius: 5px; } } } } } </style>