- 2022.11.22
- JavaScript
- GIV_wataru
javascriptでアコーディオンパネルを作成する方法
アコーディオンパネルとは、項目をクリックしたり、タップしたりすることで、隠れているパネルを表示できる機能です。

これによって、ユーザーが見たいパネルの内容はクリックして見ることができ、見たくないパネルの内容はクリックしないでスルーできるようになります。
今回は、上記の質問項目のアコーディオンパネルをjavascriptで実装する方法を解説します。
javascriptでアコーディオンパネルを作成する手順
javascriptでアコーディオンパネルを作成するためのコードは次のとおりです。
▢HTML
<ul class="qanda_box"> <li class="qanda_content"> <div class="question open" data-is-answeropen="true">質問1</div> <div class="answer"> <p class="answer_content">テキストテキストテキストテキストテキストテキスト</p> </div> </li> <li class="qanda_content"> <div class="question" data-is-answeropen="false">質問2</div> <div class="answer"> <p class="answer_content">テキストテキストテキストテキストテキストテキスト</p> </div> </li> <li class="qanda_content"> <div class="question" data-is-answeropen="false">質問3</div> <div class="answer"> <p class="answer_content">テキストテキストテキストテキストテキストテキスト</p> </div> </li> <li class="qanda_content"> <div class="question" data-is-answeropen="false">質問4</div> <div class="answer"> <p class="answer_content">テキストテキストテキストテキストテキストテキスト</p> </div> </li> </ul>
▢CSS
.qanda_box { width: 600px; margin: 0 auto; margin-top: 40px; list-style: none; } .qanda_box .qanda_content .question { position: relative; border-bottom: dotted 1px #e4e4e4; font-weight: bold; padding: 10px; cursor: pointer; } .qanda_box .qanda_content .question::before { position: absolute; right: 10px; top: 50%; width: 20px; height: 3px; background-color: #000000; content: ""; } .qanda_box .qanda_content .question::after { position: absolute; right: 10px; top: 50%; width: 20px; height: 3px; -webkit-transform: rotate(90deg); transform: rotate(90deg); background-color: #000000; content: ""; } .qanda_box .qanda_content .question.open::after { display: none; } .qanda_box .qanda_content .answer { overflow: hidden; height: 0px; width: 100%; margin-top: 5px; margin-bottom: 5px; -webkit-transition: all 0.5s; transition: all 0.5s; background-color: #e4e4e4; } .qanda_box .qanda_content .answer .answer_content { padding: 10px; margin: 0px; }
▢js
const questions = document.querySelectorAll(".question") questions.forEach((question) => { window.addEventListener('load', () => { if (question.dataset.isAnsweropen === "true") { const firstquestion = questions[0] const firstanswer = questions[0].nextElementSibling const firstanswercontent = firstanswer.children[0] const targetHeight = firstanswercontent.offsetHeight firstanswer.style.height = targetHeight + "px" }; }); question.addEventListener("click", function () { if (question.dataset.isAnsweropen === "false") { const question = event.currentTarget const answer = question.nextElementSibling const answercontent = answer.children[0] const targetHeight = answercontent.offsetHeight answer.style.height = targetHeight + "px" question.dataset.isAnsweropen = true question.classList.add("open") } else { const question = event.currentTarget const answer = question.nextElementSibling answer.style.height = 0 + "px" question.dataset.isAnsweropen = false question.classList.remove("open") } }) })
では以下にて詳しい実装方法を解説していきます。
まずはCSSでパネルを非表示にする
.qanda_box .qanda_content .answer { overflow: hidden; height: 0px; width: 100%; margin-top: 5px; margin-bottom: 5px; -webkit-transition: all 0.5s; transition: all 0.5s; background-color: #e4e4e4; }
まずはCSSで隠したいコンテンツを隠しましょう。heightは0pxにして、パネルの内容が表示されないようにoverflow:hideenを使っています。またパネルを開く、閉じる際にアニメーションの動きをつけたかったのでtransitionも使用しています。
javascriptでアコーディオンパネルを実装する手順
CSSでパネルを非表示にしたら、javascriptを使ってアコーディオンパネルを実装していきましょう。
const questions = document.querySelectorAll(".question")
querySelectorAllは、指定したクラスを全て取得できるメソッドです。取得したクラスは配列に格納されます。今回は質問文の箇所に設定してあるクラス(question)を取得して、変数に格納しています。
questions.forEach((question) => { })
forEach()は配列の一つ一つに対して処理を行えるメソッドです。
question.addEventListener("click", function () { if (question.dataset.isAnsweropen === "false") {} })
addEventListener(“click”では、クリックイベントを設定できます。これにより「クリックしたらパネルが開く、閉じる」といった機能を実装できます。
また.dataset.isAnsweropenでは、データ属性を設定しています。これは、HTMLのquestionクラスに付与している「data-is-answeropen=”false”」と関連づけられています。
値はfalseと設定していて、条件分岐を行っています。「falseならば、隠れているパネルを表示する」「trueならば、表示されているパネルを隠す」といった処理を設定することで、アコーディオンパネルを実装できます。
const question = event.currentTarget const answer = question.nextElementSibling const answercontent = answer.children[0] const targetHeight = answercontent.offsetHeight answer.style.height = targetHeight + "px" question.dataset.isAnsweropen = true
上記はif (question.dataset.isAnsweropen === “false”) { 以降の記述で、コンテンツを開く処理を行うための記述になります。「event.currentTarget」とは、イベントが起きた要素を差します。今回の場合は、質問1、2、3、4の箇所のいずれかの箇所を指します。
nextElementSiblingとは、次の要素のことを指します。questionの次の要素は、回答が記載してあるパネルのanswerになります。つまりquestion.nextElementSiblingはanswerのことを指します。
answer.children[0]とは、answerの子要素を指します。そのため今回はanswer_content
クラスのことを指します。
answercontent.offsetHeightの「.offsetHeight」は要素の高さを指定しています。今回はanswerクラスの子要素である、answer_contentクラスの高さを指定しています。
answer.style.height = targetHeight + "px"
ここでは子要素の高さを、親要素のanswerクラスに代入しています。元々answerクラスの高さは0に設定してコンテンツが隠れている状態でしたが、子要素の高さを代入することでパネルが表示されるようになります。
question.dataset.isAnsweropen = true
高さを代入したら、データ属性の値をtrueにしましょう。これでtrueの場合はコンテンツが表示されている状態になり、コンテンツが開いている状態ならばコンテンツを閉めるといった設定ができるようになります。
else { const question = event.currentTarget const answer = question.nextElementSibling answer.style.height = 0 + "px" question.dataset.isAnsweropen = false }
表示されたパネルを隠すための記述です。隠すためにはanswerクラスの高さを0にすればよいです。高さを0にしたらデータ属性の値をfalseにするのも忘れないようにしましょう。
質問1の回答だけを開いた状態にする方法
本記事で制作したアコーディオンパネルは、デフォルトの状態の場合、質問1の回答のみ開いている状態になっています。何故この状態にしたかというと、パネルの仕組みがユーザーに分かりやすいと思ったからです。
質問1の回答のみ開く状態にするためのコードは次のとおりです。
window.addEventListener('load', () => { if (question.dataset.isAnsweropen === "true") { const firstquestion = questions[0] const firstanswer = questions[0].nextElementSibling const firstanswercontent = firstanswer.children[0] const targetHeight = firstanswercontent.offsetHeight firstanswer.style.height = targetHeight + "px" }; });
では以下にて詳しく解説します。
window.addEventListener('load', () => { if (question.dataset.isAnsweropen === "true") {
今回はクリックされたらではなく、ページが読み込まれたら質問1の回答部分を開くといった処理にしたいので、「addEventListener(‘load’, () => 」を使っています。
そして回答部分を開いた状態にするので、条件分岐ではtrueを使っています。
const firstquestion = questions[0]
今回は1番目のquestionだけ指定したいので、questions[0]を変数に格納しています。
const firstanswercontent = firstanswer.children[0] const targetHeight = firstanswercontent.offsetHeight firstanswer.style.height = targetHeight + "px"
このあたりの箇所は、前述で説明した回答部分を開いた状態にする方法とそこまで変わりません。前述と同じように記述します。
質問に「+」「-」マークをつける方法
本記事のアコーディオンパネルでは、回答部分が開いている状態なら「-」マーク、閉まっている状態なら「+」マークを表示させています。こちらの切り替えもjavascriptで実装しています。
cssの疑似クラスを使って「+」「-」マークを表示
.qanda_box .qanda_content .question::before { position: absolute; right: 10px; top: 50%; width: 20px; height: 3px; background-color: #000000; content: ""; } .qanda_box .qanda_content .question::after { position: absolute; right: 10px; top: 50%; width: 20px; height: 3px; -webkit-transform: rotate(90deg); transform: rotate(90deg); background-color: #000000; content: ""; }
上記のようにquestionクラスに::before、::afterの疑似クラスを付与することで、「+」「-」マークを表示させています。
classの付け外しで「+」「-」を切り替える
▢HTML
<div class="question open" data-is-answeropen="true">質問1</div>
▢css
.qanda_box .qanda_content .question.open::after { display: none; }
▢js
question.classList.add("open") question.classList.remove("open")
今回は上記のようにopenクラスの付け外しで、「+」「-」マークの付け外しを実装しています。
GIV株式会社は、埼玉県川越市にあるWEB(ホームページ)制作会社です。お困りごと、ご相談、お気軽にご連絡ください。お問い合わせは、こちらから。