【Vue.js】アニメーション付きアコーディオンメニューを作る

完成イメージ

detailsタグを使わず、JavaScriptで動的に開閉するアコーディオンメニューです。

コンポーネントとして作り使い回せるので、複数の設置にも対応しています。

実装方法

1. コンポーネント実装

Vue.component("accordion", {
template: `
<div class="accordion">
<div class="title" @click="open()">
<slot name="title"></slot>
<transition name="rotate" mode="out-in">
<i class="fas fa-chevron-up" v-if="isOpen" key="rotate1"></i>
<i class="fas fa-chevron-down" v-else key="rotate2"></i>
</transition>
</div>
<transition name="open">
<div class="accordion-content" v-if="isOpen">
<slot name="content"></slot>
</div>
</transition>
</div>`,
data: function () {
return {
isOpen: false,
};
},
methods: {
open: function () {
this.isOpen = !this.isOpen;
},
},
});
new Vue({
el: "#app",
});

2. コンポーネントを呼び出す

<div id="app">
<accordion>
<div slot="title">タイトル</div>
<div class="content" slot="content">
<p>ここに内容</p>
</div>
</accordion>
<accordion>
<div slot="title">タイトル</div>
<div class="content" slot="content">
<p>ここに内容</p>
</div>
</accordion>
<accordion>
<div slot="title">タイトル</div>
<div class="content" slot="content">
<p>ここに内容</p>
</div>
</accordion>
</div>

3. スタイルをあてる

メニューのスタイル

.accordion {
max-width: 70%;
margin: 10px auto;
}
.title:hover {
cursor: pointer;
opacity: 0.8;
}
.title {
padding: 15px;
margin-bottom: 10px;
background-color: #eee;
border-radius: 5px;
}
.title > div {
display: inline-block;
font-weight: bold;
}
.title i {
float: right;
line-height: 1.3;
}
.content {
padding: 0 15px;
margin-bottom: 10px;
}

開閉時のアニメーション

.open-enter-active {
animation: open 0.2s;
}
.open-leave-active {
animation: open 0.2s linear reverse;
}
@keyframes open {
0% {
opacity: 0;
transform: translateY(-5px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
.rotate-enter-active {
animation: rotate 0.2s linear;
}
@keyframes rotate {
0% {
transform: rotate(180deg);
}
}

あとは適宜デザインを整えてあげれば完成です。