本文へスキップ
  1. Web BENTO JS
  2. カテゴリ一覧
  3. アコーディオン
03 / ACCORDION 12 パーツ

JSアコーディオン実装 12選

コピペで動くアコーディオン(開閉パネル)のサンプル集です。プレビューは実際にクリックで開閉できます。HTML / CSS / JS タブでコードを確認し、全部コピーを押せば1回の貼り付けで完成します。すべて依存ライブラリなしのバニラJSで、data-bnto-* 属性による自動初期化式です。

該当するパーツが見つかりませんでした。

クリックでなめらかに開閉します。中身の高さは自動計算不要(CSS Gridの0fr→1fr)。

ベーシック

<div class="bnto-acc" data-bnto-acc>
  <button type="button" class="bnto-acc-head">
    見出しテキスト
    <svg class="ar" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
  </button>
  <div class="bnto-acc-body"><div>
    <div class="bnto-acc-inner">サンプル文章がここに入ります。</div>
  </div></div>
</div>
使い方のコツ

最初から開いた状態にしたいときは、<div class="bnto-acc is-open"> のように is-open を付けておくだけです。開閉スピードは --dur を変更してください。

排他式。ひとつ開くと、ほかの項目は自動で閉じます。
サンプル文章です。項目ごとに自由な長さの説明文を入れられます。
サンプル文章です。開くと他の項目は自動で閉じます。

排他式(1つだけ開く)

<!-- .it を必要なだけ並べる。最初に開くものに is-open -->
<div class="bnto-acc2" data-bnto-acc-solo>
  <div class="it is-open">
    <button type="button" class="hd">見出し1
      <svg class="ar" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="bd"><div><div class="in">サンプル文章1</div></div></div>
  </div>
  <div class="it">
    <button type="button" class="hd">見出し2
      <svg class="ar" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="bd"><div><div class="in">サンプル文章2</div></div></div>
  </div>
</div>
使い方のコツ

料金プランの説明やステップ式の案内など「同時に1つだけ見せたい」場面に向いています。全部閉じることも可能です(開いている項目をもう一度クリック)。

商品到着後7日以内であれば可能です。
5,000円以上のご注文で無料になります。

FAQ(よくある質問)

<div class="bnto-faq" data-bnto-faq>
  <div class="it">
    <button type="button" class="hd"><span class="q">Q</span>質問文をここに</button>
    <div class="bd"><div><div class="in">回答のサンプル文章をここに</div></div></div>
  </div>
  <!-- .it を質問の数だけ繰り返し -->
</div>
使い方のコツ

FAQはページ内で疑問を解消できる、SEOとユーザビリティの両面で有効なコンテンツです。なお、FAQPage 構造化データによる検索結果でのQ&A表示(リッチリザルト)は、現在は政府機関・医療系など一部のサイトに限定されています。

+アイコンが45度回転して×になります。疑似要素だけで作っているので画像不要。

プラス→バツ

<div class="bnto-acc4" data-bnto-acc4>
  <button type="button" class="hd">
    見出しテキスト
    <span class="pl" aria-hidden="true"></span>
  </button>
  <div class="bd"><div>
    <div class="in">サンプル文章がここに入ります。</div>
  </div></div>
</div>
使い方のコツ

「+=もっと見られる」という記号は直感的で、FAQやメニューと好相性です。回転角を 135deg にすると勢いのある動きになります。

開いている項目がひと目で分かるスタイル。ナビゲーションにも向いています。

塗りつぶしヘッダー

<div class="bnto-acc5" data-bnto-acc5>
  <button type="button" class="hd">
    見出しテキスト
    <svg class="ar" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
  </button>
  <div class="bd"><div>
    <div class="in">サンプル文章がここに入ります。</div>
  </div></div>
</div>
使い方のコツ

「今どこが開いているか」が色で分かるので、項目数が多いページに向きます。文字色とのコントラストには注意してください(白文字なら背景はやや濃い色に)。

サンプル文章です。開いたカードは影が濃くなり浮き上がります。
サンプル文章です。各カードは独立して開閉できます。

カード分離型

<div class="bnto-acc6" data-bnto-acc6>
  <div class="it">
    <button type="button" class="hd">見出し
      <svg class="ar" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="bd"><div><div class="in">サンプル文章</div></div></div>
  </div>
  <!-- .it を必要な数だけ -->
</div>
使い方のコツ

カード同士が離れているので、項目が独立した内容のとき(サービス紹介・機能説明など)に最適です。背景に薄い色を敷くとカードの浮きが際立ちます。

サンプル文章です。開いている項目の左にアクセントラインが付きます。
サンプル文章です。背景もほんのり色付きます。

左ライン点灯

<div class="bnto-acc7" data-bnto-acc7>
  <div class="it">
    <button type="button" class="hd">見出し
      <svg class="ar" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="bd"><div><div class="in">サンプル文章</div></div></div>
  </div>
  <!-- .it を必要な数だけ -->
</div>
使い方のコツ

マニュアルや利用規約など、長いリストで「現在地」を示したいときに便利です。ホバー時にも薄いラインを出すとさらに操作しやすくなります。

details/summary 版 1
HTML標準のdetails要素。name属性を揃えるとJSなしで排他開閉になります。
details/summary 版 2
こちらを開くと1が自動で閉じます(ブラウザ標準機能)。

details/summary(JS不要)

<!-- name を揃えると1つだけ開く(JS不要のブラウザ標準機能) -->
<div class="bnto-acc8">
  <details name="faq">
    <summary>質問1</summary>
    <div class="in">回答1</div>
  </details>
  <details name="faq">
    <summary>質問2</summary>
    <div class="in">回答2</div>
  </details>
</div>
使い方のコツ

JSを1行も書かずに動く最軽量の選択肢です。キーボード操作・スクリーンリーダー対応もブラウザ任せでOKです。中身が検索エンジンに読まれやすいのも利点です。なお、name属性による排他開閉は2024年前後にリリースされた主要ブラウザで利用できます。古いブラウザでは排他にならず、個別開閉として動作します(壊れはしません)。なめらかな高さアニメが必要なら他のパーツをお使いください。

サンプル文章です。上のボタンで全項目を一括開閉できます。
サンプル文章です。各項目は個別にも開閉できます。
サンプル文章です。長い仕様書やFAQで活躍します。

一括開閉ボタン付き

<!-- .ctrl の2ボタンで一括開閉。.it は必要なだけ -->
<div class="bnto-acc9" data-bnto-acc-all>
  <div class="ctrl">
    <button type="button" class="all-open">すべて開く</button>
    <button type="button" class="all-close">すべて閉じる</button>
  </div>
  <div class="it">
    <button type="button" class="hd">見出し1
      <svg class="ar" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="bd"><div><div class="in">サンプル文章1</div></div></div>
  </div>
  <div class="it">
    <button type="button" class="hd">見出し2
      <svg class="ar" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="bd"><div><div class="in">サンプル文章2</div></div></div>
  </div>
</div>
使い方のコツ

仕様書・FAQ・利用規約など、項目数が多い長いページで活躍します。「すべて開く」にしておけばブラウザのページ内検索(Ctrl+F / ⌘F)で折りたたまれた本文もヒットしやすくなり、印刷前の展開にも便利です。各項目は個別にも開閉できます。

3件
5,000円以上のご注文で送料無料、それ未満は全国一律550円です。
商品到着後7日以内であれば、未開封に限り返品を受け付けています。
クレジットカード・銀行振込・コンビニ払いに対応しています。

検索で絞り込めるFAQ

<!-- .it を必要なだけ並べる。質問文・回答文の両方が検索対象 -->
<div class="bnto-acc10" data-bnto-filteraccordion>
  <div class="srch">
    <input class="kw" type="search" placeholder="キーワードで絞り込み" aria-label="FAQを絞り込み">
    <span class="cnt" aria-live="polite"></span>
  </div>
  <div class="it">
    <button type="button" class="hd">質問1
      <svg class="ar" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="bd"><div><div class="in">回答1</div></div></div>
  </div>
  <div class="it">
    <button type="button" class="hd">質問2
      <svg class="ar" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="bd"><div><div class="in">回答2</div></div></div>
  </div>
  <!-- 0件のときに表示されるメッセージ -->
  <p class="ns" hidden>一致する質問が見つかりませんでした</p>
</div>
使い方のコツ

項目数が多いFAQページの定番強化です。item.textContent 全体を検索対象にしているため、質問文と回答文のどちらでもヒットします。0件時のメッセージは .ns のテキストを書き換えるだけです。ヒット数の表示が不要なら .cnt を削除してもそのまま動きます。

プランの詳細は子アコーディオンから開けます。親を閉じると子も一緒に閉じます。
月額980円。個人利用向けの基本機能が使えます。
月額2,980円。チーム利用と優先サポート付きです。
1か月単位で契約でき、いつでも解約できます。子の無い項目は普通のアコーディオンとして動きます。

入れ子アコーディオン

<!-- 親の .in の中に .sub → 子の .it を入れる(構造は親と同じ) -->
<div class="bnto-acc11" data-bnto-nestaccordion>
  <div class="it">
    <button type="button" class="hd">親項目
      <svg class="ar" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="bd"><div><div class="in">親の説明文
      <div class="sub">
        <div class="it">
          <button type="button" class="hd">子項目
            <svg class="ar" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
          </button>
          <div class="bd"><div><div class="in">子の説明文</div></div></div>
        </div>
      </div>
    </div></div></div>
  </div>
</div>
使い方のコツ

カテゴリ→詳細のような階層のあるFAQやメニューに向いています。親を閉じると子も自動で閉じるので、開閉状態の食い違いが起きません。CSSは >(直下セレクター)で親と子を区別しているため、さらに深い階層もそのまま入れ子にできますが、読みやすさの面では2階層程度がおすすめです。

ご注文から2〜3営業日で発送します。項目を開くとURLに #faq-post が付きます。
到着後7日以内なら返品できます。#付きのURLを共有すると、この項目が開いた状態で表示されます。
クレジットカードと銀行振込がご利用いただけます。

ハッシュ連動アコーディオン

<!-- 各 .it に一意の id を付ける。#id 付きURLで開くと自動で開いてスクロール -->
<div class="bnto-acc12" data-bnto-hashaccordion>
  <!-- デモ用の疑似リンク(本番では <a href="#faq-post"> でOK) -->
  <div class="lk">
    <button type="button" class="jp" data-target="faq-post">#faq-post を開く</button>
    <button type="button" class="jp" data-target="faq-return">#faq-return を開く</button>
  </div>
  <div class="it" id="faq-post">
    <button type="button" class="hd">配送について
      <svg class="ar" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="bd"><div><div class="in">回答1</div></div></div>
  </div>
  <div class="it" id="faq-return">
    <button type="button" class="hd">返品について
      <svg class="ar" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="bd"><div><div class="in">回答2</div></div></div>
  </div>
</div>
使い方のコツ

「FAQのこの項目を見て」と#付きURLで直接共有できるのがポイントです。id#faq-post のように意味の分かる名前にし、ページ内の他の要素と重複しないようにしてください。URLの書き換えには history.replaceState を使っているので、開閉のたびにブラウザ履歴が増えることはありません。

JSアコーディオン実装の基礎知識

アコーディオンは、クリックでコンテンツを開閉して限られたスペースに情報を整理する定番UIです。FAQ・料金プランの詳細・スペック表など「全員には不要だが、必要な人には見せたい」情報と相性が抜群です。このページのサンプルはすべて依存ライブラリなしのバニラJavaScriptで、jQueryもフレームワークも不要です。

使い方は、HTML / CSS / JSの3タブをそれぞれ貼り付けるか、「全部コピー」ボタンでひとまとめになったコードを1回貼り付けるだけです。初期化は data-bnto-* 属性の自動検出式なので、同じページに何個置いても、うっかりコードを2回貼っても壊れません。

開閉アニメーションの仕組み(height:autoのアニメ問題)

CSSは height: auto へのアニメーションができないため、従来は中身の高さをJSで測る必要がありました。このページでは grid-template-rows: 0fr → 1fr を使うモダンな手法を採用しています。高さの計測が一切不要で、中身が画像や可変テキストでもなめらかに動きます。

アクセシビリティのポイント

見出しには必ず <button> を使うこと(divのclickだけではキーボードで操作できません)。開閉状態は aria-expanded で支援技術に伝えます。サンプルはどちらも実装済みです。セマンティクスを最優先するなら、ブラウザ標準の <details>/<summary> 版も用意しています。

SEOとの関係

アコーディオンで隠したコンテンツも、HTMLとして存在していればGoogleにインデックスされます(display:noneでもモバイルファーストインデックスでは評価対象)。FAQを実装する場合、FAQPage 構造化データを付けること自体に問題はありませんが、検索結果でのQ&A表示(リッチリザルト)は現在、政府機関・医療系など一部のサイトに限定されている点は知っておくと安心です。

「全部コピー」と「分けて貼る」の使い分け

「全部コピー」を使うと、HTML・CSS・JavaScriptがひとつの自己完結ブロックとしてコピーされるので、1回の貼り付けだけですぐ動きを確認できます。動作のお試しや、1ページ完結のLPに組み込むときはこの方法が手軽です。

一方、本番サイトへ本格的に組み込む場合は、CSSはスタイルシート(.cssファイル)へ、JavaScriptは</body>直前や共通の.jsファイルへ、HTMLは使いたい場所へと分けて貼るのが一般的です。スタイルとスクリプトを1か所に集約できるため、複数ページ・複数パーツで使い回すときの管理がしやすく、ブラウザのキャッシュも効きやすくなります。なお、同じパーツをページ内で何度も使う場合でも、CSSとJSを貼るのは1回だけで大丈夫です(初期化スクリプトが該当要素すべてに自動で効きます)。

よくある質問

コピーしたアコーディオンはそのまま動きますか?
はい。「全部コピー」を押すとHTML・CSS・JSがひとつの自己完結ブロックになってコピーされ、ページに貼り付けるだけで動きます。ライブラリの読み込みは一切不要です。
同じページに複数設置しても大丈夫ですか?
大丈夫です。初期化スクリプトは data 属性で対象を自動検出し、初期化済みの要素はスキップするため、複数設置してもコードを2回貼っても壊れません。
開閉のなめらかなアニメーションはどう実現していますか?
CSS Grid の grid-template-rows を 0fr から 1fr へ変化させる方法を使っています。中身の高さをJavaScriptで測る必要がなく、可変コンテンツでもなめらかに開閉します。
アクセシビリティには対応していますか?
見出しは button 要素なのでキーボード(Enter / Space)で操作でき、開閉状態は aria-expanded 属性でスクリーンリーダーに伝わります。details/summary 版はブラウザ標準のセマンティクスをそのまま使えます。
このページのパーツはAIコーディングツールでも使えますか?
はい。Claude CodeやCursorのようにWebページを読めるAIには、このページのURLとパーツ名(例:「排他式(1つだけ開く)」)を伝えるだけで実装を指示できます。AIがWebを読めない場合は、「全部コピー」で取得した自己完結ブロックをチャットに貼り付けて調整を頼むのが確実です。改変後のコードは、公開前に動作確認することをおすすめします。

関連カテゴリ

アコーディオンと組み合わせて使いやすいパーツはこちらです。