【JavaScript】「アコーディオンメニュー」をライブラリなしで作る方法【アニメーションつき】

※この記事にはプロモーションが含まれています。
しゅーた(@chibasyuta)です!
この記事では「アコーディオンメニュー」の作り方を解説します。
具体的にはライブラリを使わずに「JavaScript」だけでアニメーションつきのアコーディオンメニューを作る方法をご紹介します。
「jQuery」などのライブラリは使わず、そのままの「JavaScript」だけを使って実装することで、「JavaScript」の勉強になりますし、カスタマイズしやすい内容となるかと思います。
また、簡易的な「アコーディオンメニュー」なら、HTML要素だけで作ることができるので、そちらの方法もあわせて解説します。
この記事の内容!
- 「アコーディオンメニュー」とは何か
- 「details」と「summary」を使った簡単な実装
- 「JavaScript」を使った実装
それでは内容へ入ります!
「アコーディオンメニュー」とは何か
主に多くの情報をコンパクトに整理して表示するために使われます。
名前の由来は、初めは隠れている部分が、クリックと同時に表示されるのが、楽器のアコーディオンのようなので、このような名前で呼ばれています。広がったり縮んだりする動きが似ていますよね。
FAQ、商品の詳細説明など、多くの情報を扱う場面で特に役立ちます。
「details」と「summary」要素を使った簡単な「アコーディオンメニュー」の作り方!
本格的な「アコーディオンメニュー」の前に、HTML要素だけで作れる簡単な「アコーディオンメニュー」の作り方から解説します!
<div class="container">
<details>
<summary>項目</summary>
<p>えーっとまあ、内容です。</p>
</details>
<details>
<summary>項目</summary>
<p>えーっとまあ、内容です。</p>
</details>
<details>
<summary>項目</summary>
<p>えーっとまあ、内容です。</p>
</details>
</div>
.container {
width: 700px;
margin: 160px auto;
}
details {
font-size: 50px;
margin-bottom: 10px;
cursor: pointer;
}
このように「details」と「summary」要素を使うと、「JavaScript」を使わずとも「アコーディオンメニュー」が作れます。
「details」要素で本文を含めた全体を囲います。
そして、そしてその本文の内容を要約したものや、項目名を「summary」要素で囲えばできあがりです!「summary」要素は非表示の際に表示するテキストを囲います。
デフォルトでブラウザが表示・非表示をクリックで切り替えられるようにしてくれます。
簡単な「アコーディオンメニュー」なら、この方法でサクッと作れますね。
ですが、アニメーションを付けたりとか、そういった細かい調節がしたい場合は「JavaScript」を使った実装が必要になります。
改訂3版JavaScript本格入門
JavaScriptの文法から現場での書き方まで、1冊でしっかり押さえたい方向けの定番書です。
Amazonのアソシエイトとして、当ブログは適格販売により収入を得ています。
「JavaScript」を使ってカスタマイズ可能な「アコーディオンメニュー」を作る方法!
このようにアニメーションをつけるなど、カスタマイズ性が高い洗練された「アコーディオンメニュー」を作るには「JavaScript」を使えば実装できます!
具体的には、パッと表示・非表示が切り替わるのではなく、アニメーションさせる感じにします。アニメーションがあった方がアコーディオンっぽいです。
では、その方法をまとめますね!
「HTML」ファイル!
<div class="container">
<dl>
<div class="box">
<dt>項目</dt>
<dd>内容です。内容です。内容です。内容です。内容です。内容です。内容です。</dd>
</div>
<div class="box">
<dt>項目</dt>
<dd>内容です。内容です。内容です。内容です。内容です。内容です。内容です。</dd>
</div>
<div class="box">
<dt>項目</dt>
<dd>内容です。内容です。内容です。内容です。内容です。内容です。内容です。</dd>
</div>
<div class="box">
<dt>項目</dt>
<dd>内容です。内容です。内容です。内容です。内容です。内容です。内容です。</dd>
</div>
<div class="box">
<dt>項目</dt>
<dd>内容です。内容です。内容です。内容です。内容です。内容です。内容です。</dd>
</div>
<div class="box">
<dt>項目</dt>
<dd>内容です。内容です。内容です。内容です。内容です。内容です。内容です。</dd>
</div>
</dl>
</div>
「HTML」ファイルはこんな感じで、「dl」「dt」「dd」要素を使って説明付きのリストを作ります。
「CSS」ファイル!
.container {
width: 700px;
margin: 80px auto;
}
.box {
margin-bottom: 30px;
}
dt {
background-color: #ddd;
padding: 16px 40px;
display: flex;
justify-content: space-between;
font-size: 30px;
margin-bottom: 4px;
}
dt::after {
content: "+";
}
.box.show dt::after {
content: "ー";
}
dd {
height: 0px;
overflow: hidden;
transition-duration: 0.4s;
font-size: 30px;
}
「dd」要素の「height」は「0px」にしてください。
そして「JavaScript」から「show」というクラスを、つけたり外したりすることで、「+」と「-」を切り替えています。
あとは「CSS」ファイルにお好みでいろいろ設定してください。
「JavaScript」ファイル!
let dts = document.querySelectorAll('dt');
dts.forEach( (dt) => {
dt.addEventListener('click', () => {
dt.parentElement.classList.toggle('show');
const content = dt.nextElementSibling;
const isOpen = content.offsetHeight > 0;
if ( isOpen ) {
content.style.height = '0px';
} else {
content.style.height = `${content.scrollHeight}px`;
}
});
} );
後は 「JavaScript」で「アコーディオンメニュー」の動き部分を作ればOKです!
まず、全ての「dt要素」を「document.querySelectorAll(‘dt’)」で取得します。
そして、それらに「forEach」で一つ一つ処理を加えていきます。
具体的には「addEventListener」で「click」したときの処理を追加します。
今回はクリックした「dt」要素の親要素の「.box」クラスがついた「div」要素に「show」というクラスをつけたり外したりすることで、非表示の時の「+」アイコンと、表示の時の「-」アイコンを切り替えます。
さらに「isOpen」という変数で「メニュー」が表示モードなのか非表示モードなのかを管理ます。
具体的には「content.offsetHeight > 0;」ですね。「content」の高さが0よりも大きければ、表示されていると解釈できます。「offsetHeight」で要素の現在の高さが取得できます。
そして、クリックされた際に「内容が非表示」であれば「content.style.height = `${content.scrollHeight}px`」として、「content」に高さを指定してあげればOKです。「content.scrollHeight」で要素の本来の高さが取得できます。(画面に表示されているかではない純粋な高さが取れます。)
クリックされた際に「内容が表示」されているのであれば、「content.style.height = `0px`;」として、高さを無くしてあげればOKです。
「display」の切り替えではなく「height」を切り替える
アニメーションさせるためには「display」の切り替えではなく「height」を切り替えてください。
「display」を「block」と「none」で切り替えると、それらは離散値であるため、アニメーションさせることができません。中間というのがないからです。
なので「height」を切り替えてください。
2つ目をクリックしたら、1つ目を閉じる処理を追加!
let dts = document.querySelectorAll('dt');
dts.forEach( (dt) => {
dt.addEventListener('click', () => {
// 追加部分
dts.forEach( (dt) => {
dt.nextElementSibling.style.height = '0px';
dt.parentElement.classList.remove('show');
} );
const content = dt.nextElementSibling;
const isOpen = content.offsetHeight > 0;
if ( isOpen ) {
content.style.height = '0px';
} else {
content.style.height = `${content.scrollHeight}px`;
// toggleからaddに変更してここに移動
dt.parentElement.classList.add('show');
}
});
} );
このように、コードを追加することで、複数のメニューが同時に表示されないようにすることができます。
どちらを使うべき?
「details」と「summary」
おすすめの場合: 時間をかけず簡単に作りたいとき。
用途: ドキュメントやFAQのような簡単なUIで十分な場合。
「JavaScript」を使った方法
おすすめの場合: デザインや挙動を細かく調整したいとき。
まとめ!
簡単な方法として「details」と「summary」を使うのも良いですが、デザインや動きを自由にカスタマイズしたい場合は「JavaScript」を使った実装を検討してみてください。
両者を使い分けることで、プロジェクトに合った最適な「アコーディオンメニュー」を作ることができます!
それでは、こんな感じでこの記事を終わります!
またね!
1冊ですべて身につくJavaScript入門講座
JavaScriptを、動くものを作りながら基礎から通して学びたい方向けの入門書です。
Amazonのアソシエイトとして、当ブログは適格販売により収入を得ています。
\ めちゃくちゃ便利です /
毎日の新着を、通知で受け取る
最新の技術の動きを1分で読める記事にして、毎日お届けします。登録は無料で、いつでもやめられます。
iPhone は「ホーム画面に追加」すると通知を受け取れます
iPhone では、Safari で開いたままだと通知を出せない決まりになっています。このブログをホーム画面に置くと、アプリのように通知が届くようになります。下の5つを順番に行ってください。1分ほどで終わり、料金はかかりません。
-
共有ボタンを押す
いま見ているこのページのまま、画面のいちばん下を見てください。真ん中にある四角から上向きの矢印が出ているマークが共有ボタンです。これを1回タップします。
下のバーが見えないときは、画面を指で少し下に動かすと出てきます。
-
「ホーム画面に追加」を選ぶ
画面の下からメニューが出てきます。メニューを指で上に動かして下のほうを表示し、「ホーム画面に追加」(+のマーク)を探してタップします。
見当たらないときは、メニューの中の「その他」や「…」を押すと出てきます。
-
右上の「追加」を押す
「ホーム画面に追加」という画面に変わります。名前は「皇帝ペンギン」のままで大丈夫です。右上の「追加」をタップします。
-
ホーム画面のアイコンから開く
Safari を閉じてホーム画面に戻ると、ペンギンの絵の「皇帝ペンギン」というアイコンが増えています。これをタップして開きます。
ここが大事です。Safari からではなく、必ずこのアイコンから開いてください。
-
「通知をオンにする」→「許可」
開くと、画面の下に「通知をオンにする」という黄色いボタンが出ます。タップすると確認が出るので、「許可」を選びます。「通知をオンにしました」と出たら完了です。
次の日から、新しい記事が出るたびに通知が届きます。やめたいときは、記事の下の「この端末の通知をやめる」を押すか、アイコンを削除してください。
LINE や X のアプリ内で開いている場合は、先に右下や右上のメニューから「Safari で開く」を選んでください。
動画でじっくり学びたい方は YouTube メンバーシップ へ。