【JavaScript】アコーディオンを使ったUIの実装方法を初心者向けにわかりやすく解説
はじめに
多くのWebサイトで利用されるアコーディオンという仕組みは、要素をクリックするとコンテンツが開閉するUIパターンを指します。
これをうまく活用すると、サイト上での情報整理や見た目のわかりやすさに大いに役立ちます。
ただ、いざJavaScriptでアコーディオンを実装しようとすると、どこから手を付けるべきか迷う方もいるかもしれません。
ここでは、初心者の皆さんにもわかりやすいように、具体的なコード例とともにアコーディオンの使い方を整理してみます。
この記事を通じて、なぜアコーディオンが便利なのか、どう実装すればスムーズに動くのかを理解していただければと思います。
この記事を読むとわかること
- JavaScriptアコーディオンの基本的な仕組み
- 実務で役立つ利用シーンとそのメリット
- JavaScriptを使った実装例と動作のポイント
- UI面やアクセシビリティを考慮するうえでの注意点
アコーディオンとは何か
アコーディオンの概要
アコーディオンは、見出しをクリックした際に、その下の詳細情報が折りたたみ式に開閉するインターフェースを指します。
普段からFAQページやサイドメニューなどで見かける場面も多いのではないでしょうか。
必要な情報だけを表示して、不要な情報は閉じておくことで、画面の整理ができます。
また、画面をスクロールしなくても視覚的に情報をまとめられる点が、多くのサイトで採用されている理由といえるでしょう。
アコーディオンが必要とされる理由
UIの見やすさ
アコーディオンを使う最大の利点のひとつは、見やすさです。
たとえば、FAQページで質問一覧を全部展開してしまうと、スクロールが増えてしまい、ユーザーが探しにくくなることがあります。
しかし、アコーディオンを採用することで、最初は質問だけを表示し、ユーザーが興味を持ったところをクリックすると回答が表示されるようにできます。
こうすることで情報過多を防ぎ、必要に応じて情報が展開されるため、ユーザー体験が向上するのです。
スペースの有効活用
コンテンツを小さくまとめられる点も魅力です。
デザイン上の制約から、あまり大きなスペースを取りづらいケースでも、アコーディオンを使えば小さな領域に多くの情報を詰め込めます。
特にスマートフォン向けのサイトや小さめの画面では、コンパクトなUIが重要なので、アコーディオンがよく活用されます。
実務での利用シーン
- FAQやヘルプページ: 質問リストと回答を対にする形で表示
- サイドメニュー: カテゴリをクリックするとサブメニューが開く形式
- プロジェクト管理ツール: タスクの詳細やコメント欄を折りたたむ
これらのシーンでは、アコーディオンを取り入れることで、余分な表示を避け、操作する人が必要な情報だけ確認できる仕組みを提供できるわけです。
アコーディオンの基本構造
HTML要素の考え方
アコーディオンは、シンプルに考えると「見出し」と「内容」の2つの要素で成り立っています。
HTMLで作る場合は、見出し部分に button
や div
などのタグを使い、クリック時にクラスを切り替えて内容を開閉するのが一般的です。
例えば以下のような構造を考えます。
<div class="accordion"> <div class="accordion-item"> <button class="accordion-header">見出し1</button> <div class="accordion-content"> <p>ここに詳細内容が入ります</p> </div> </div> <div class="accordion-item"> <button class="accordion-header">見出し2</button> <div class="accordion-content"> <p>ここにも詳細内容が入ります</p> </div> </div> </div>
それぞれの .accordion-item
ごとに、アコーディオンを開く/閉じるという状態を管理するようにします。
CSSやJavaScriptでクラス名を付け替えることで、開閉動作を実現します。
CSSの設定例
アコーディオンの中身を隠すために、CSSで表示・非表示を制御します。
たとえば、閉じている状態は高さを0にするか、 display: none;
を使う方法があります。
.accordion-content { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; } .accordion-item.active .accordion-content { max-height: 200px; /* 適宜大きめに設定しておき、実際の内容量に合わせて動くようにする */ }
このように、通常は max-height
を0にし、クリックされたアイテムのクラスに .active
を付与して max-height
を指定してあげると、スムーズに開閉するアコーディオンになります。
ただし、 max-height
にする場合は、実際の内容量が大きいと固定値の設定が難しい点に注意が必要です。
JavaScriptでの基本的な動作管理
アコーディオンの開閉は、最終的にJavaScriptでコントロールします。
具体的には、ボタンなどをクリックした時に、 parentElement
や closest()
メソッドで .accordion-item
を取得し、クラス名の付け替えを行います。
document.addEventListener("DOMContentLoaded", () => { const accordionHeaders = document.querySelectorAll(".accordion-header"); accordionHeaders.forEach((header) => { header.addEventListener("click", () => { const accordionItem = header.parentElement; // .accordion-itemを取得 accordionItem.classList.toggle("active"); }); }); });
このコードでは、各 .accordion-header
をクリックしたタイミングで、その親要素( .accordion-item
)に対して .active
を付けたり外したりしています。
その結果、先ほど説明したCSSの accordion-item.active .accordion-content
が適用されたり外れたりすることで、中身が開いたり閉じたりするわけです。
アコーディオン実装のコード例
シンプルなアコーディオンの例
ここからは、実際に使えそうなHTML/CSS/JavaScriptの例を、あらためてまとめて紹介します。
まずは最もシンプルなアコーディオンの実装例を見てみましょう。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>シンプルなアコーディオン例</title> <style> .accordion-content { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; } .accordion-item.active .accordion-content { max-height: 300px; } /* 見た目を少し整える */ .accordion-header { background-color: #eee; padding: 10px; cursor: pointer; border: none; text-align: left; width: 100%; } .accordion-item { margin-bottom: 5px; border: 1px solid #ccc; } </style> </head> <body> <div class="accordion"> <div class="accordion-item"> <button class="accordion-header">見出し1</button> <div class="accordion-content"> <p>コンテンツ1の詳細な内容がここに表示されます。</p> </div> </div> <div class="accordion-item"> <button class="accordion-header">見出し2</button> <div class="accordion-content"> <p>コンテンツ2の詳細な内容がここに表示されます。</p> </div> </div> <div class="accordion-item"> <button class="accordion-header">見出し3</button> <div class="accordion-content"> <p>コンテンツ3の詳細な内容がここに表示されます。</p> </div> </div> </div> <script> document.addEventListener("DOMContentLoaded", () => { const headers = document.querySelectorAll(".accordion-header"); headers.forEach(header => { header.addEventListener("click", () => { const item = header.parentElement; item.classList.toggle("active"); }); }); }); </script> </body> </html>
このサンプルでは、特定の見出しをクリックすると、そのアイテムだけが .active
クラスを持つようになります。
それによって、 accordion-content
がスライドダウンしてくるイメージで開閉します。
一つだけ開くようにするバリエーション
シンプルな実装例では、クリックするたびに複数のアコーディオンが同時に開いてしまう可能性があります。
もし「常に一つだけ開いてほしい」という場合は、クリックするたびに他のアイテムの .active
を外す実装にすると良いでしょう。
document.addEventListener("DOMContentLoaded", () => { const headers = document.querySelectorAll(".accordion-header"); headers.forEach(header => { header.addEventListener("click", () => { // いったん全ての .accordion-item から .active を外す const allItems = document.querySelectorAll(".accordion-item"); allItems.forEach(item => item.classList.remove("active")); // クリックした要素だけactiveを付与 const thisItem = header.parentElement; thisItem.classList.add("active"); }); }); });
このようにすれば、一度に複数のアコーディオンが開くことはなくなります。
実務での使い分けポイント
- 複数同時に開く: FAQページなど、複数の回答を並行して見たい場面に適している
- 一つだけ開く: メニュー項目のように、1つを開くと他を閉じておきたい場合に使う
上記のように、アコーディオンの開閉ルールは状況によって変わります。
自分が作りたい仕組みに合った方法を選択すると良いでしょう。
実務でありがちなアコーディオンの注意点
UXとアニメーション
アコーディオンを実装する際には、アニメーションの速度や開閉のトリガーがユーザーの体感に大きく影響します。
あまりにもアニメーションが遅いと、ユーザーが「反応が悪い」と感じる場合があります。
逆に早すぎると自然に見えず、違和感が出てくることもあります。
そのため、CSSの transition: 0.3s
から 0.5s
の範囲で試してみたり、開閉時にアイコンを回転させるなどの調整を細かく行うと、使いやすいUIに近づきやすいです。
アクセシビリティを意識する
見出しとして button
タグを使う場合、スクリーンリーダー等が「ボタンがある」ことを認識しやすいです。
一方、単なる div
や span
にクリックイベントを仕込む場合は、キーボード操作で焦点を当てられなくなる可能性があります。
特に公共性の高いWebサイトや、より多くのユーザー層に使ってもらいたいサイトでは、アクセシビリティをしっかり考えることが大切です。
以下の点が最低限のポイントです。
- 見出し用のボタン要素には
aria-expanded
などの属性を付与する - 折りたたんでいる内容に
aria-hidden="true"
を付けるなど、状態を明確に示す - キーボード操作だけでも開閉ができるよう、
tabindex
やbutton
要素の利用を心がける
もちろん、開発要件やデザインの制約にもよりますが、ユーザー体験を広く考えると、このあたりに気を配ると良いでしょう。
内容量が大きい場合
アコーディオン内にテキストや画像を大量に配置するケースもあります。
そんなときは単に .active
の切り替えだけでなく、アコーディオンを開く前にデータを読み込むような工夫が必要になるかもしれません。
例えば、外部APIから情報を取得して表示するような場面では、クリックのタイミングでAJAXリクエストを走らせることもあります。
その場合、開いた際の読み込み速度が遅いと、ユーザーにストレスを感じさせるかもしれません。
インジケータを表示したり、「読み込み中…」などのメッセージを差し込む実装を検討すると、現場での運用がスムーズになります。
アコーディオンの実務的な活用シーン
サイトのFAQセクション
実際によく見かける活用例の一つがFAQページです。
質問の一覧があって、クリックすると回答が開くというのは、ほぼ定番のUIになっています。
FAQ以外にも、商品説明ページで「詳細を見る」という形でアコーディオンを使い、ユーザーが必要な時だけ詳しいスペックや素材情報を表示するケースも多いです。
アパレル系サイトなら「サイズ表の開閉」をアコーディオンにすると整理しやすいでしょう。
管理画面や社内ツール
社内システムでも、情報の表示非表示を切り替える場面があります。
たとえば、多数のタスクが並ぶプロジェクト管理画面で、タスクをクリックするとコメント欄や詳細が開く構造を作りたい場合があります。
テーブル表示だけでは情報が煩雑になるので、一部のカラムをアコーディオンにまとめておくと、管理者にとって見通しが良くなるかもしれません。
特に、業務効率化を目的としたツールでは、必要な情報を最小限に絞りつつ、必要なときに詳細をすぐ確認できるのが重要です。
スマートフォン対応
スマートフォンの画面は狭いため、コンテンツをそのまま並べると縦に長いページになりがちです。
そこでアコーディオンを取り入れると、必要に応じて折りたたんで表示をコンパクトにできます。
いわゆるハンバーガーメニューとしてサイドメニューをアコーディオンで実装することもあります。
もし横幅が狭い画面での操作性を考えるなら、ボタンの大きさや余白、アニメーション速度などを調整し、タッチ操作でも押しやすくすることが望ましいです。
JavaScriptアコーディオン実装で押さえるポイント
クリックイベントの管理方法
単純に click
イベントを付けるだけであれば、DOMを取得して関数をセットするだけです。
しかし、アコーディオンの項目数が増えると、あまり多くのイベントリスナーを設定しすぎるとコードが煩雑になることもあります。
その場合、アコーディオン全体をラップする要素にイベント委譲を活用する方法も考えられます。
「どの要素がクリックされたか」を取得して、クラスの付け替えを行うと、HTML構造が増えても拡張しやすくなります。
document.addEventListener("DOMContentLoaded", () => { const accordionContainer = document.querySelector(".accordion"); accordionContainer.addEventListener("click", (e) => { // クリックした要素がaccordion-headerなら処理を進める if (e.target && e.target.classList.contains("accordion-header")) { const item = e.target.parentElement; item.classList.toggle("active"); } }); });
このやり方なら、一か所でイベントを拾って処理できるため、アコーディオンアイテムが増えてもコードがシンプルに保ちやすいです。
コンポーネント化の検討
大規模なプロジェクトになると、JavaScriptやフレームワークを使ってUIコンポーネントとしてアコーディオンを作る場面も出てきます。
ReactやVue.jsなどを使っているなら、再利用しやすいコンポーネントとして切り出し、状態管理やスタイルの切り替えをまとめて制御することが一般的です。
たとえばReactの場合は、アコーディオンをひとつのコンポーネントと捉え、折りたたみの状態をuseState
で管理し、開閉の状態に応じてスタイルや要素の表示を制御します。
このように実装すれば、複数ページで同じアコーディオン機能を使いたいときにも使い回せるため、保守性が向上するでしょう。
CSSフレームワークを用いる場合
BootstrapやTailwind CSSのようなCSSフレームワークでも、アコーディオンのスタイルがプリセットで用意されていることがあります。
それをカスタマイズして使う手段もありますが、アニメーションや開閉のロジックまで完全に提供されるものと、部分的にしかサポートされないものがあります。
フレームワークに頼ると、デザイン上のメリットが大きい反面、自由度が下がる場合もあるため、自分たちのプロジェクトの要件に合った方法を選ぶと良いでしょう。
よくあるトラブルと対処法
開閉アニメーションが一瞬で終わってしまう
CSSで transition
を設定していても、要素の display: none;
と組み合わせるとアニメーションが効かない場合があります。
これは、要素が「無い」状態になっているため、表示された瞬間にアニメーションが発火できないことが原因です。
対処法としては、 display
プロパティではなく max-height
や opacity
を使って、「要素はあるけど表示サイズや透明度が0」という状態にし、 transition
で変化させるとスムーズになります。
スマートフォンでの動作が不安定
タッチイベントを考慮しなかったり、ボタンのサイズが小さいといった理由で、スマートフォンでクリック(タップ)がうまく反応しないケースもあります。
最低限、タップしやすい大きさ(44px四方など)を確保しておくと良いでしょう。
また、タッチに対して hover
のスタイルを設定していると、期待していない挙動をするケースもあります。
そのため、メディアクエリなどを利用して、スマートフォンの場合は hover
の効果を無効にするなどの対応も検討してください。
多段アコーディオンの管理
アコーディオン内にさらにアコーディオンがあるような多段構造を作る場合、イベント伝播やCSSの指定が複雑になることがあります。
クリックイベントが親要素にまで伝播して、意図せず外側のアコーディオンも操作されてしまうことなどが代表的なトラブルです。
もし多段構造が必要な場合は、各レベルでイベントを止める (event.stopPropagation()
) などを行い、誤作動が起こらないように注意すると良いでしょう。
アコーディオンとSEOの関係
昨今の検索エンジンはJavaScriptの実行にも対応していますが、アコーディオンで折りたたまれた情報がどのように評価されるかを気にする声もあるかもしれません。
必要以上にコンテンツを隠すと、ユーザーから見ても検索エンジンから見ても内容が分かりづらい場合があります。
とはいえ、適切に見出しやマークアップを行っていれば、検索エンジンがアコーディオンを展開して内容をクローリングできるケースも多いです。
重要なのは、ユーザーが求めている情報を、わかりやすく提供するという点です。
コンテンツを全部表示すると見づらいならアコーディオンを用い、適切なマークアップを加えることでSEO的にも悪影響を最小限に抑えることができます。
まとめ
ここまで、JavaScriptでアコーディオンを実装する際の基本構造やサンプルコード、注意点などを解説してきました。
アコーディオンをうまく使えば、多くの情報をコンパクトに整理でき、ユーザーが読みやすいインターフェースを作ることができます。
UIの見た目を洗練させたいとき、FAQページを作りたいとき、サイドメニューを表示したいときなどに役立つでしょう。
開閉のスクリプト自体はシンプルでも、アニメーションの速度調整やアクセシビリティへの配慮によって、使いやすさが大きく変わります。
実装の際は、「一度に複数開くかどうか」や「多段アコーディオンを作るかどうか」などの要件にあわせてカスタマイズし、ユーザーが快適に操作できるかどうかを念頭に置いてみてください。
ぜひ今回のポイントを参考にしながら、実務のシーンにあったアコーディオンを実装してみてください。