アコーディオンを実装したいけれど、JavaScript で書く方法・JavaScript なしで書く方法・アニメーション付き・排他制御・入れ子と複数のパターンがあり、自分の用途にはどれが合うか分からない、ということはないでしょうか。FAQ・ヘルプ・サイドナビ・規約とユースケースごとに最適なパターンは違うはずなのに、選び方の指針が見つからないという相談もよく耳にします。

この記事では、アコーディオンの代表的な実装パターンを7種類取り上げます。

  1. 早見表での全体俯瞰
  2. 選び方フローチャート
  3. 各パターンの概要と詳しい実装記事への誘導
  4. シリーズ全体で採用している共通の設計ルール

までを1記事で押さえる構成です。本記事自体はコードを掲載しない俯瞰特化型で、各パターンの実装コードは詳細記事へ誘導します。

この記事で分かること
  • アコーディオンの代表的な実装パターン7種類の早見表(実装言語・同時オープン数・アニメ有無・入れ子対応・推奨ユースケース)
  • 自分の要件に合うパターンを特定する4段階の決定木フローチャート
  • 各パターンの概要・向いているユースケース・メリット・注意点
  • シリーズ全体で採用している共通の設計ルール(FLOCSS 命名・真実の源・キーボード操作・モーション配慮など)
  • WAI-ARIA Authoring Practices(APG)との整合ポイント
  • アコーディオン実装でよく出る5つの疑問への回答

アコーディオン7パターン早見表

まずは7つの実装パターンを一覧で見比べてみましょう。「JavaScript を書きたいか・書きたくないか」「同時に複数開きたいか」「アニメーションを付けたいか」「入れ子にしたいか」のどれが自分の要件に直結するかを軸にすると選びやすくなります。

パターン名実装言語同時オープン数アニメ入れ子対応推奨ユースケース
<details> ネイティブ実装HTML のみ制限なしなし可能ブログ補足・規約・利用ガイド
チェックボックスハックHTML + CSS制限なしなし注意必要JS禁止環境・装飾優先のシンプル折りたたみ
バニラJS + ARIA 基本形HTML + CSS + JS制限なしなし可能設定パネル・基本的な開閉UI全般
複数同時オープン(一括操作付)HTML + CSS + JS制限なしなし可能価格表・スペック比較・ヘルプセンター
排他制御(1つだけ開く)HTML + CSS + JS1つだけなし可能FAQ・ヘルプ・項目数が多いリスト
高さアニメーション付きHTML + CSS + JS制限なしあり可能LP・ブランドサイト・演出重視のUI
入れ子アコーディオンHTML + CSS + JS制限なしなし自身が入れ子カテゴリ階層付きFAQ・サイトマップ・章節構造

最初に見るのは「実装言語」の列です。ここで JS を書くか書かないかという最も大きな分岐が判断できます。次に「同時オープン数」と「アニメ」で挙動を決め、最後に「推奨ユースケース」で自分の用途と照らし合わせる流れが効率的です。

この後の章では、選び方フローチャートで決定木を辿りながら自分の要件に合うパターンに辿り着き、その後で各パターンの概要を確認できる構成にしています。決定木で候補を絞ってから概要を読むと、読み進めるコストが下がります。

選び方フローチャート

7パターンのどれを選ぶか迷ったら、次の4段階の決定木を上から順に辿ってみてください。「JavaScript を書くか・書かないか」が最も大きな分岐で、書く場合はさらに「どんな挙動が必要か」で枝分かれします。

Q1. JavaScript を書きたい?
├─ NO → Q2-A. 最小限の HTML タグだけで作れたら十分?
│        ├─ YES → 「<details> ネイティブ実装」
│        └─ NO  → 「チェックボックスハック」(CSS のみでカスタマイズしたい場合)
│
└─ YES → Q2-B. どんな挙動が必要?
         ├─ 「基本の開閉だけ」 → 「バニラJS + ARIA 基本形」
         ├─ 「複数同時に開閉・一括操作したい」 → 「複数同時オープン(一括操作付)」
         ├─ 「1つだけ開きたい(FAQ的)」 → 「排他制御(1つだけ開く)」
         ├─ 「開閉に高さアニメーションを付けたい」 → 「高さアニメーション付き」
         └─ 「多階層(親子)にしたい」 → 「入れ子アコーディオン」

各分岐の判断材料を補足します。

  • Q1(JS の要否): 「JS を書きたくない・JS が動かない環境でも閉じた状態で読めるようにしたい」場合は NO。「排他制御・一括操作・アニメ・入れ子の発火制御など、高度な挙動が必要」な場合は YES
  • Q2-A(JS なし派): <details> はブラウザ標準で、キーボード操作やスクリーンリーダー対応まで自動で処理されます。開閉アイコンを完全に置き換えたい場合はチェックボックスハックの方が CSS で自由に作り込めます
  • Q2-B(JS あり派): 同時オープン数・アニメ・入れ子の3要件は組み合わせも可能ですが、本シリーズの個別記事では基本パターン単体での実装を解説しています。まずは1つの軸で選び、必要に応じて組み合わせを検討してください

迷ったら バニラJS + ARIA 基本形 から始めると、後で複数同時オープン・排他制御・アニメーション・入れ子のいずれにも拡張しやすい設計になっています。基本形のコードを土台にすれば、応用パターンへの移行は差分を足すだけで済みます。

7パターンそれぞれの概要

ここからは各パターンの概要を順に紹介します。各セクションでは「どう動くか」「向いているユースケース」「メリット」「注意点」「詳しい実装記事への誘導」を1セクションで完結させています。コードは載せず、選択判断に必要な情報に絞っています。

<details> ネイティブ実装

ブラウザに最初から備わっている <details> / <summary> 要素を使うだけで、JavaScript を1行も書かずにアコーディオンが完成します。クリックすると open 属性が付与され、キーボード操作やスクリーンリーダー対応もブラウザがすべて処理します。

  • 向いているユースケース: ブログの補足説明・規約や利用ガイドの章節構造
  • メリット: 実装コストが最小、アクセシビリティ対応が自動、JS が落ちても閉状態で安全
  • 注意点: 開閉アイコンの細かいカスタムが難しい場面がある、高度な挙動には別途 JS が必要

→ 詳しい実装は JavaScript不要でアコーディオンを作る2つの方法|<details> とチェックボックスハックを比較【コピペOK】 へ。

チェックボックスハック

<input type="checkbox">:checked 擬似クラスを兄弟セレクタで参照し、CSS だけで開閉を表現する手法です。<label> をクリック対象として <input> を視覚的に隠して使います。<details> よりも CSS で自由にデザインできるのが特徴です。

  • 向いているユースケース: JS が使えない環境・装飾を優先したい折りたたみ
  • メリット: CSS の自由度が高い、JS 不要、ブラウザの互換性も良好
  • 注意点: スクリーンリーダーが「アコーディオン」ではなく「チェックボックス」として読み上げる

→ 詳しい実装は JavaScript不要でアコーディオンを作る2つの方法|<details> とチェックボックスハックを比較【コピペOK】 へ。

バニラJS + ARIA 基本形

<button>aria-expanded を付与し、JavaScript で true / false を切り替える「現場のデファクト」とも言える実装です。本文パネルは hidden 属性で制御し、aria-controls でボタンとパネルを関連付けます。WAI-ARIA APG の Accordion パターンに沿った構成です。

  • 向いているユースケース: 基本的な開閉 UI 全般・設定パネル・コーポレートサイトの折りたたみ
  • メリット: ARIA 対応が明示的に書ける、後続パターンへの拡張が容易
  • 注意点: JS が必要、<details> よりも書くコード量が増える

→ 詳しい実装は バニラJSで作るアコーディオン|aria-expanded で実装するARIA対応の基本形【コピペOK】 へ。

複数同時オープン(一括操作付)

複数の項目を同時に開いたままにできる挙動で、「すべて開く / すべて閉じる」の一括操作ボタンを併設するパターンです。一括操作の状態変化はフォーカス位置から離れた場所で起こるため、aria-live でスクリーンリーダーに通知する設計が標準です。

  • 向いているユースケース: 価格表・スペック比較・ヘルプセンター・公開資料の章節
  • メリット: 自由度の高い閲覧体験、一括操作で「全部見たい」ニーズに即応できる
  • 注意点: 項目数が多いとスクロールが伸びる、aria-live の通知設計に少し配慮が要る

→ 詳しい実装は アコーディオンの開閉制御パターン|複数同時オープン vs 排他制御の作り方を比較【コピペOK】 へ。

排他制御(1つだけ開く)

常に最大1つの項目だけが開く挙動で、別の項目を開くと現在開いている項目が自動で閉じます。FAQ のように項目数が多く答えが長い場面で散らかりを防げます。実装の核はクリックされたヘッダー以外を閉じる際に「自分自身を除外する」ガード処理です。

  • 向いているユースケース: FAQ ページ・ヘルプセンター・項目数が多く答えが長いリスト
  • メリット: 画面が常にすっきり保たれる、迷ったらこれで失敗しにくい
  • 注意点: 複数項目を見比べたい場面には不向き、切り替えるたびに前の項目の内容が見えなくなる

→ 詳しい実装は アコーディオンの開閉制御パターン|複数同時オープン vs 排他制御の作り方を比較【コピペOK】 へ。

高さアニメーション付き

grid-template-rows: 0fr → 1fr のトランジションと :has() 親方向セレクタを組み合わせて、コンテンツの高さに応じた自然な開閉アニメーションを実現するパターンです。max-height ハックのような不自然な速度変動が起きず、height: auto のままトランジションが効きます。

  • 向いているユースケース: LP・ブランドサイト・演出を重視する UI
  • メリット: UI の品質が上がる、max-height ハック特有の速度のばらつきや上限値の管理が不要
  • 注意点: :has() のブラウザ対応状況の確認が要る、実装コストが基本形より上がる

→ 詳しい実装は アコーディオンに高さアニメーションを付ける作り方|grid-template-rows: 0fr→1fr × :has() で実装【コピペOK】 へ。

入れ子アコーディオン

親アコーディオンの本文の中に子アコーディオンを置く構造で、カテゴリ階層付きの FAQ やサイトマップ風ナビゲーションに使われます。実装の核は「親と子のクリックハンドラが二重発火しないようにする」スコープガードで、header.closest(".c-accordion") === root で「ヘッダーが直属する root」を厳密に判定します。

  • 向いているユースケース: カテゴリ階層付き FAQ・ヘルプセンターの階層ナビ・規約の章節構造
  • メリット: 階層構造を視覚的に伝えられる、closest ベースのガードは他の入れ子 UI にも応用可能
  • 注意点: 入れ子の深さは1段階までを目安にすると読みやすさを保てる

→ 詳しい実装は 入れ子アコーディオンの作り方|親と子の二重発火を防ぐスコープガード実装【コピペOK】 へ。

シリーズ共通の設計ルール

シリーズの個別記事5本+実装すべてに共通する設計ルールがあります。どのパターンを選んでも下記の方針を踏まえておくと、アクセシビリティ・保守性・拡張性で困ることが少なくなります。コーディング初学者〜中級者がまず押さえておくと安心な6つのポイントを順に紹介します。

クラス名は FLOCSS の c-accordion__* で揃える

すべての実装パターンで CSS のクラス名は c-accordion をコンポーネント本体とし、c-accordion__header(クリック対象)・c-accordion__body(本文パネル)・c-accordion__content(内側ラッパー)の BEM 形式で統一しています。クリック対象の HTML 要素は実装方式によって変わります(<button> / <summary> / <label>)。一方でクラス名は c-accordion__header で共通にしている点が要で、これにより CSS セレクタはどの実装方式でも同じ書き方で動き、コピペで他パターンに転用しても CSS の改修が最小限で済みます。FLOCSS の全体像は別記事の FLOCSSとは?基本の考え方と実際の書き方を分かりやすく解説 へ。

開閉状態の「真実の源」を1つに絞る

開閉状態を表現する場所を1つに絞る、というのが本シリーズの設計上の核です。「真実の源(single source of truth)」と呼ばれる考え方で、状態を複数箇所で持つと、片方が更新されたのにもう片方が古いまま残る不整合が起きやすくなります。実装パターンごとの集約先は次の通りです。

  • JS 実装系: aria-expanded 属性(<button> に付与)
  • <details> 系: open 属性
  • チェックボックスハック系: :checked 擬似クラス

いずれの場合も is-open のような独自クラスは付与しません。1つの属性に絞ることで、JavaScript・CSS・スクリーンリーダーがすべて同じ情報を見る状態を保てます。

キーボード操作とアクセシビリティ

クリック対象にはネイティブ意味論を持つ要素を使い、<div onclick> は使いません。<button> を使うとブラウザが Enter / Space での起動・Tab でのフォーカス移動・スクリーンリーダーへの「ボタン」読み上げを自動で処理してくれます。フォーカスリングは消さず :focus-visible で視認性の高い枠線を表示し、クリック対象の最低サイズは タップ領域 44 × 44px 以上を確保します。JS 実装系で <button> を使う場合は type="button" を必ず明示し、装飾用のアイコン <span> には aria-hidden="true" を付与します。

本文の表示・非表示は hidden 属性で制御する

JS 実装系では本文の表示制御に HTML の hidden 属性を使い、JavaScript から display: none を付与しません。HTML として閉状態が読み取れるため可視性が高く、JavaScript が落ちた場合でも閉じた状態として安全にフォールバックします。例外的にチェックボックスハック系は :checked ~ セレクタ構造上 hidden 属性が機能しないため、display: none / block で代替します。

モーション配慮(prefers-reduced-motion

OS の「視差効果を減らす」設定を尊重し、@media (prefers-reduced-motion: reduce) でトランジションを無効化する記述をシリーズ全パターンで採用しています。前庭感覚障害や乗り物酔いを起こしやすい人にとって、過剰なアニメーションは身体的な不快感を生むため、UI 側で無効化する配慮が必要です。ホバースタイルは @media (any-hover: hover) and (pointer: fine) で囲み、タッチデバイスで :hover がタップ後に張り付く挙動を回避します。

同一ページ複数配置の安全性

シリーズ全パターンが、同一ページ内に複数のアコーディオンを配置しても破綻しない設計です。id 属性は c-accordion-{識別子}-{種別}-{連番} 形式で命名して衝突を回避します。JS 実装系では .c-accordion[data-accordion] セレクタで対象を特定するため、data-accordion 属性のないアコーディオン(<details> 系・チェックボックスハック系)には JS が触れません。同一ページに JS 実装系と JS なし系が混在しても、両者は独立して動作します。

WAI-ARIA APG 整合のポイント

シリーズの実装は WAI-ARIA Authoring Practices(W3C による ARIA 実装パターン集)の Accordion パターンに沿った構成を採用しています。主要な属性は APG 推奨と完全一致する3点を採用しました。aria-expanded はクリック対象に付与して true / false を切り替え、aria-controls でクリック対象とパネルの id を関連付け、role="status" aria-live="polite" を一括操作のフォーカス位置と状態変化位置が離れる場合に設置しています。

一方で、APG の一部の推奨は採用していません。矢印キーによる項目間移動ArrowUp / ArrowDown)は APG 推奨ですが、シリーズではより一般的な Tab キーでの移動を採用しています。Tab だけで完結する方が学習コストが低く、リスト構造で実装した場合のブラウザ標準の挙動とも合致するためです。aria-disabled も使用せず、一括操作ボタンの無効化には HTML 標準の disabled 属性で対応しています。

よくある質問(FAQ)

JavaScript を書きたくない場合、どのパターンを選べばよいですか?

折りたたみの基本動作だけで十分なら <details> ネイティブ実装がおすすめです。HTML 標準要素なのでブラウザがキーボード操作・スクリーンリーダー対応をすべて処理してくれます。一方、デザインを細かくカスタマイズしたい・<details> の開閉アイコンを完全に置き換えたい場合は、チェックボックスハックが選択肢になります。ただしチェックボックスハックはスクリーンリーダーが「アコーディオン」ではなく「チェックボックス」として読み上げる点には注意してください。

FAQ で「1つだけ開く」と「複数同時に開ける」のどちらが良いですか?

ユースケース次第です。質問が独立していてユーザーが複数の質問を見比べたい場合は複数同時オープンが向いています(公開価格表・スペック比較など)。質問数が多く答えが長く上下にスクロールしながら読む場合は排他制御の方が画面が散らかりません(FAQ ページ全般・ヘルプセンターなど)。迷ったら排他制御を選んでおくと見やすさで失敗しにくいです。

高さアニメーションは付けた方がよいですか?

UI の品質を上げる効果はありますが必須ではありません。シリーズの実装ではアニメーション無しでも開閉が完結するため、アニメーションは「あれば嬉しい」程度の位置づけです。実装コストとしては grid-template-rows: 0fr → 1fr + :has() の CSS 技法を理解する必要があり、対応ブラウザの確認も求められます。シンプルさを優先するなら無し、演出のリッチさを優先するなら有り、で選び分けてください。OS の「視差効果を減らす」設定が有効な場合はアニメーションが自動で無効化される実装になっている点も覚えておくと安心です。

アコーディオンに <div onclick> を使わずに <button> を使う理由は何ですか?

<button> を使うとブラウザがキーボード操作(Enter / Space)・フォーカス移動(Tab)・スクリーンリーダーへの「ボタン」読み上げを自動で処理してくれるためです。<div onclick> だと JavaScript でクリックは動きますが、キーボードでの起動・支援技術への通知は自前で実装する必要があります。アクセシビリティ対応の負荷が大きく増えるため、シリーズの実装ではこのネイティブ意味論を最大限活用する方針を採用しています。

同じページに JS あり実装と JS なし実装を混在させても大丈夫ですか?

問題ありません。シリーズの JS 実装は .c-accordion[data-accordion] セレクタで対象を特定しており、data-accordion 属性のないアコーディオン(<details> 系・チェックボックスハック系)には JavaScript が触れない設計です。同一ページに「JS で制御するアコーディオン」と「JS 不要のアコーディオン」を共存させても、両者が干渉せずに動作します。id 属性も衝突しないよう命名規則で分離してあります。

まとめ

この記事では、アコーディオンの代表的な実装パターン7種類を、早見表・選び方フローチャート・各パターンの概要・共通の設計ルール・FAQ で俯瞰しました。ポイントを整理します。

  • アコーディオンには JS あり・JS なしを含めて代表的な実装パターンが7種類ある
  • 選び方の最も大きな分岐は JavaScript を書くか・書かないか。書かないなら <details> ネイティブ実装かチェックボックスハック、書くなら基本形・複数同時オープン・排他制御・アニメーション付き・入れ子から要件に応じて選ぶ
  • どのパターンを選んでも、FLOCSS 命名・真実の源を1つに絞る・ネイティブ意味論を優先・hidden 属性で制御・モーション配慮・同一ページ複数配置の安全性の6本柱は共通で押さえておくと安心
  • 各パターンの詳しい実装は、本記事末尾の関連記事ブロックから個別記事へ進めます

アコーディオンは小さな UI ですが、JS の有無・挙動・アニメ・入れ子と選択肢が多く、最初に俯瞰しておくと後の意思決定がスムーズになります。本記事の早見表と選び方フローチャートをブックマークしておき、案件やポートフォリオで実装する時の参照点として使っていただければ嬉しいです。

【関連記事】

【シリーズ:アコーディオンUIシリーズ】