今回はJavaScriptでのアコーディオンの作り方をまとめてみたいと思います。
こんなかんじのデモを作ってみました。
See the Pen
ExNJbYr by notebook (@orange-notebook)
on CodePen.
質問と書いてあるタブをクリックすると、対応した回答の表示・非表示が切り替わります。
また質問タブの右にあるプラスとマイナスのマークも
回答の表示状況によって連動して切り替わるようになっています。
またjQueryでのアコーディオンの作りかたについては、
こちらの記事でまとめているのでよろしければご覧ください。
おおまかな役割
まずHTML / CSS / JavaScriptの役割分担的なことをまとめてみたいと思います。
いろいろな作り方があるので、今回の作りかたに関してとなります。
HTML:
クリックできる「質問」タブと、クリニックに伴って現れる「回答」部分を作る。
CSS:
- デフォルトでは回答タブを非表示にする。
- 回答タブにactiveクラスがついたら、回答部分を表示するように設定する。
- 質問タブにカーソルがあたったときポインターにして、クリックできると分かるようにする。
- 質問タブの右部分にあるプラスマークを作る。(今回は擬似要素を使用)
- 質問タブにactiveクラスがついたら、プラスの代わりにマイナスマークを表示させる。
JavaScript:
- 「質問」タブがクリックされたら、クリックされた質問タブとその質問に対応する回答タブのactiveクラスを付け外しの処理をする。
ではそれぞれもうすこし詳しくみていきましょう。
HTML
HTMLの全体像はこんなかんじになっています。
<div class="accordion__container">
<div class="accordion__tab">質問 1</div>
<div class="accordion__content">
<p>回答 1</p>
</div>
<div class="accordion__tab">質問 2</div>
<div class="accordion__content">
<p>回答 2</p>
</div>
<div class="accordion__tab">質問 3</div>
<div class="accordion__content">
<p>回答 3</p>
</div>
</div>
「.accordion__container」クラスのついたdivタグを用意しました。
アコーディオンメニューの箱のイメージで、全体のサイズ調整などを行います。
その中に質問タブにあたる「.accordion__tab」と、回答部分にあたる「.accordion__content」のクラスがついたdivを交互に書いています。
CSS
CSSの全体像はこんなかんじになっています。
.accordion__container {
max-width: 500px;
width: 90%;
margin: 20px auto 0;
border: 1px solid gainsboro;
border-bottom: 0;
}
.accordion__tab {
padding: 10px 20px;
cursor: pointer;
position: relative;
border-top: 0;
border-bottom: 1px solid gainsboro;
}
.accordion__tab::after {
content: "+";
position: absolute;
right: 20px;
}
.accordion__tab.active::after {
content: "ー";
}
.accordion__content {
padding: 10px 20px;
display: none;
background: whitesmoke;
border-bottom: 1px solid gainsboro;
}
.accordion__content.active {
display: block;
}
デフォルトでは回答部分を非表示にしておきたいので、
「.accordion__content」に「display: none;」を指定します。
.accordion__content {
padding: 10px 20px;
display: none;
background: whitesmoke;
border-bottom: 1px solid gainsboro;
}
また質問タブがクリックされて、回答タブにactiveクラスがついたら回答タブを表示させるようにします。
そのため「.accordion__content.active」に「display: block;」を指定しておきます。
.accordion__content.active {
display: block;
}
今回、質問部分の「.accordion__tab」はdivタグで作っています。
そのままだとカーソルをのせても、クリックできるかわかりにくいので「cursor: pointer;」でカーソルの形になるようにします。
.accordion__tab {
padding: 10px 20px;
cursor: pointer;
position: relative;
border-top: 0;
border-bottom: 1px solid gainsboro;
}
そして質問タブの右にあるプラスマークを、CSS擬似要素の::afterで作っていきます。
まず親要素にあたるタブ「.accordion__tab」に「position: relative;」を指定し、擬似要素「.accordion__tab::after」に下記プロパティを設定します。
- position: absolute;
- right: 20px; (.accordion__tabのpaddingに合わせて位置調整。)
- content: “+”; (今回はアイコンではなく、普通の記号で作っています。)
.accordion__tab::after {
content: "+";
position: absolute;
right: 20px;
}
また質問タブがクリックされ、回答が表示されたら記号をプラスからマイナスに変更します。
そのため「.accordion__tab」に「active」クラスがついた状態の「.::after」の「content」プロパティを「−」に変更します。
.accordion__tab.active::after {
content: "ー";
}
JavaScript
JavaScriptの全体像はこんなかんじになっています。
// 質問タブを変数に入れる
const tabs = document.querySelectorAll(".accordion__tab");
// 回答コンテンツを変数に入れる
const contents = document.querySelectorAll(".accordion__content");
for (let i = 0; i < tabs.length; i++) {
// 質問タブをクリックしたら発火
tabs[i].addEventListener("click", function () {
// クリックした質問タブのactiveクラスを付け替える
this.classList.toggle("active");
// クリックした質問タブのindex番号の回答コンテンツのactiveクラスを付け替える
contents[i].classList.toggle("active");
});
}
JavaScriptではまず、質問タブと回答タブの要素を変数の中に入れます。
// 質問タブを変数に入れる
const tabs = document.querySelectorAll(".accordion__tab");
// 回答コンテンツを変数に入れる
const contents = document.querySelectorAll(".accordion__content");
質問タブをクリックしたとき、クリックした質問タブのactiveクラスの付け替えを行います。
またクリックされた質問タブのindex番号に対応した回答タブにactiveクラスの付け替えをする処理を行います。
質問タブも回答タブもそれぞれ複数存在するので、繰り返し処理が必要です。
今回はfor構文で繰り返し処理をしています。
for (let i = 0; i < tabs.length; i++) {
// 質問タブをクリックしたら発火
tabs[i].addEventListener("click", function () {
// クリックした質問タブのactiveクラスを付け替える
this.classList.toggle("active");
// クリックした質問タブのindex番号の回答コンテンツのactiveクラスを付け替える
contents[i].classList.toggle("active");
});
}
以上、JavaScriptでのアコーディオンメニューの作りかたでした。
最後までお読みいただき、ありがとうございました。