[JavaScript] button要素で作るアコーディオン|スムーズな開閉を実装する方法
本記事では、button 要素とJavaScript(Vanilla JS)を使い、スムーズに開閉するアコーディオンの実装方法を紹介します。
button 要素を使用することでアクセシビリティにも配慮でき、Chrome・Edge・Firefox・Safariなど主要ブラウザでも安定して動作します。
シンプルなアコーディオンのデモ
まずは完成イメージです。
以下のCodePenでは、JavaScript(Vanilla JS)で実装したスムーズなアコーディオンを確認できます。
CodePen デモ
[JavaScript] button要素で作るスムーズなアコーディオン
See the Pen [JavaScript] button要素で作るスムーズなアコーディオン by mkl may (@mkl-may) on CodePen.
HTML
|
1 2 3 4 5 6 7 8 9 10 |
<div class="accordion"> <button class="accordion-header" type="button"> Question </button> <div class="accordion-content"> <p>Answer テキストが入ります。テキストが入ります。</p> <p>テキストが入ります。テキストが入ります。</p> </div> </div> |
アコーディオンの見出しにはbutton要素を使用します。
クリックによる開閉操作を行うUIのため、意味を持たない div 要素ではなく、操作を目的とした button 要素を使用することで、HTMLの意味付け(セマンティクス)的にも適切な実装になります。
また、button要素はキーボード操作やスクリーンリーダーにも標準対応しているため、アクセシビリティの観点からも推奨されています。
CSS
|
1 2 3 4 5 6 7 8 9 10 11 |
/* コンテンツ */ .accordion-content { max-height: 0; overflow: hidden; transition: max-height .4s cubic-bezier(0.22, 1, 0.36, 1); } /* 開いた状態のアイコン */ .accordion.active .accordion-header::after { transform: translateY(-50%) rotate(225deg); } |
初期状態ではコンテンツ部分の高さを0にし、overflow: hidden; を指定して内容を非表示にします。
JavaScriptで max-height を切り替えることで、高さが滑らかに変化するアコーディオンを実装しています。
また、矢印アイコンには擬似要素を使用し、開閉状態に応じて回転するよう設定しています。
JavaScript
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<script> document.querySelectorAll('.accordion-header').forEach(button => { button.addEventListener('click', () => { const accordion = button.parentElement; const content = accordion.querySelector('.accordion-content'); // activeクラス切り替え accordion.classList.toggle('active'); // 開閉状態を取得 const isOpen = accordion.classList.contains('active'); // 高さ制御 content.style.maxHeight = isOpen ? content.scrollHeight + 'px' : null; }); }); </script> |
JavaScriptでは、見出しのbutton要素がクリックされた際にactiveクラスを付け外ししています。
また、開閉状態に応じてmax-height を動的に変更することで、滑らかなアニメーションを実現しています。
開く場合は scrollHeight でコンテンツの実際の高さを取得し、その値を max-height へ設定します。
閉じる場合は max-height をリセットすることで、高さが0へ向かってアニメーションします。
jQueryの slideDown() や slideUp() を使用しなくても、シンプルなコードで滑らかな開閉アニメーションを実装できます。
複雑なコンテンツ向けの実装
コンテンツ内に複数段落・画像・ボタンなどを含む場合は、.accordion-content-inner を追加して親子構造にすることで、
アニメーションを担当する .accordion-content と、
レイアウトを担当する .accordion-content-inner を分離できます。
CodePen デモ
[JavaScript] button要素で作るスムーズなアコーディオン(.accordion-content-inner版)
See the Pen [JavaScript] button要素で作るスムーズなアコーディオン(.accordion-content-inner版) by mkl may (@mkl-may) on CodePen.
HTML
|
1 2 3 4 5 6 |
<div class="accordion-content"> <div class="accordion-content-inner"> <p>Answer テキストが入ります。テキストが入ります。</p> <p>テキストが入ります。テキストが入ります。</p> </div> </div> |
CSS
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* コンテンツ */ .accordion-content { max-height: 0; overflow: hidden; transition: max-height .45s cubic-bezier(0.22, 1, 0.36, 1); } /* 中身 */ .accordion-content-inner { padding: 1.5em 3em; opacity: 0; transform: translateY(-10px); transition: .3s ease; } /* 開いた状態 */ .accordion.active .accordion-content-inner { opacity: 1; transform: translateY(0); } |
inner要素を分けることで、 高さアニメーションとコンテンツ演出を分離できます。
aria-expanded に対応してアクセシビリティを向上する
アクセシビリティをさらに向上させる場合は、aria-expanded を追加することで、スクリーンリーダー利用者にも開閉状態を伝えられます。
CodePen デモ
[JavaScript] button要素で作るスムーズなアコーディオン(.accordion-content-inner + aria-expanded 版)
See the Pen [JavaScript] button要素で作るスムーズなアコーディオン(.accordion-content-inner + aria-expanded 版) by mkl may (@mkl-may) on CodePen.
HTML
|
1 2 3 |
<button class="accordion-header" type="button" aria-expanded="false"> Question </button> |
JavaScript
|
1 |
button.setAttribute('aria-expanded', isOpen); |
button要素を使用する理由
アコーディオンの見出し部分は「押すことで状態が変化する操作ボタン」です。
そのため、以下のようなdiv要素で実装するよりも、
<div class="accordion-header">
Question
</div>
button要素を使用する方が本来の目的に沿ったマークアップになります。
<button class="accordion-header" type="button">
Question
</button>
button要素には次のようなメリットがあります。
- キーボード(Enterキー、Spaceキー)で操作できる
- スクリーンリーダーでボタンとして認識される
- アクセシビリティ向上につながる
- HTMLの意味付けとして適切
details / summaryとの違い
アコーディオンは details 要素と summary 要素でも実装できます。
<details>
<summary>Question</summary>
<p>Answer</p>
</details>
details要素はHTMLだけで開閉機能を実現できるため非常に便利ですが、高さを滑らかにアニメーションさせることが難しいという特徴があります。
また、ブラウザごとにアニメーションの実装方法や挙動差を考慮する必要がある場合もあり、スムーズな開閉を重視する場合は button 要素とJavaScriptを組み合わせた実装の方が扱いやすいケースが多くあります。
用途に応じて使い分けるとよいでしょう。
まとめ
今回は、button要素とJavaScript(Vanilla JS)を使ったスムーズなアコーディオンの実装方法を紹介しました。
button要素を使用することでアクセシビリティにも配慮でき、Chrome・Edge・Firefox・Safariなど主要ブラウザでも安定して動作します。
jQueryを使わずに軽量かつアクセシブルなアコーディオンを実装したい場合は、ぜひ活用してみてください。