アコーディオンメニューを実装する際に、こんな感じでdivタグで実装してませんか?
<div class="accordion">セクション1</div>
<div class="panel">
<p>コンテンツ1</p>
</div>
これ、アクセシビリティ的にはかなり微妙で、私の出しているコーディング演習課題ではレビューでの指摘対象にしています。
え、普通にネット上のコピペして、aタグとかdivで作ってましたけど・・・
こういう方が大半かと思います。
そこで今回は、HTMLの<details>
と<summary>
要素を使った、令和に最適なアコーディオンメニューの作り方について解説します。
また、デフォルトではアニメーションがつけにくいので、そこの解説もします。
私は毎日仕事でコードレビューを行っており、details/summaryを使って実装されている方はまだ半分もいない認識ですが、これから一般化していくと思います。
それでは実装方法を詳しく見ていきましょう!
この記事を書いたのは
しょーご(@samurabrass)
当ブログ「しょーごログ」の運営者。2018年からWeb制作・フロントエンドエンジニアとして主にWordPressでのサイト制作やシステム開発のフロントエンドを担当。同時にブログとYouTubeで情報発信を行っている。駆け出しエンジニアのコーディング課題添削も行い、スクール講師を4年以上している経験を活かした分かりやすい記事制作を心がけている。
\現役エンジニアのレビュー付き/
実践レベルのコーディング課題公開中

- デザインカンプからのコーディングを経験したい
- 現役エンジニアのレビューを受けてみたい
- 即戦力級のポートフォリオを用意したい
2024年にデザインを完全リニューアルしています!
コーディングに自身をつけるにはプロからのレビューを貰うのが必須なため、制作会社も利用するレビューツールで添削をしています。

Web制作学習ロードマップにも取り入れているため、学習終了まで迷わず進むことが可能です。コーディングを本気で仕事したい方はぜひご活用ください!
\無料の入門編から本格企業サイトまで/
detailsとsummaryの基本
<details>
と<summary>
要素は、折りたたみ可能なコンテンツを作成するための専用タグです。
<details>
要素は折りたたみ可能なセクションを定義し、その中の<summary>
要素がセクションの見出しやラベルとなります。
基本的な使用方法は以下の通りです:
See the Pen Untitled by samuraibrass (@samuraibrass) on CodePen.
この構造により、ユーザーは<summary>
部分をクリックすることで、詳細コンテンツの表示・非表示を切り替えることができます。
JavaScriptを使用せずにこの動作を実現できるため、ページの読み込み速度やパフォーマンスにも好影響を与えます。
本当にシンプルでいいなら、これで終了です。
detailsとsummaryの詳細仕様
<details>
要素には、いくつかの重要な属性があります。最も一般的なのはopen
属性で、これを指定すると初期状態で詳細コンテンツが表示されます。
See the Pen Untitled by samuraibrass (@samuraibrass) on CodePen.
<details>
要素はネストすることも可能で、階層構造を持つアコーディオンメニューを作成できます。
ただし、過度に複雑な構造はユーザビリティを損なう可能性があるため、適切な深さを保つことが重要です。
また、<details>
要素にはJavaScriptで操作可能なイベントがあり、toggle
イベントを使用してコンテンツの開閉状態を検知できます。
これにより、高度なアニメーションの実装が可能となります。
ブラウザサポート状況
<details>
と<summary>
要素は、多くの最新ブラウザでサポートされています。
具体的には、Chrome、Firefox、Safari、Edge、Operaなどの主要ブラウザで問題なく動作します。

ただし、Internet Explorer 11以前のバージョンではサポートされていないため、これらのブラウザをサポートする必要がある場合は、JavaScriptによるポリフィルや代替手段を検討する必要があります。
とはいえ、今どきIE11に対応するべきプロジェクトはほとんど無いでしょう。普通に使って問題ないというのが私の認識です。
アコーディオンメニューの実装手順
アコーディオンメニューを実装する基本的な手順は以下の通りです。
- HTMLで基本構造を作成
- CSSでスタイリングを適用
- 必要に応じてJavaScriptで機能を拡張
まず、HTMLとCSSで基本的なアコーディオンを作成します。
<div class="accordion">
<details>
<summary>セクション1</summary>
<div class="content">
<p>セクション1の詳細内容がここに入ります。</p>
</div>
</details>
<details>
<summary>セクション2</summary>
<div class="content">
<p>セクション2の詳細内容がここに入ります。</p>
</div>
</details>
</div>
.accordion details {
border: 1px solid #ddd;
margin-bottom: 5px;
}
.accordion summary {
padding: 10px;
background-color: #f5f5f5;
cursor: pointer;
}
.accordion .content {
padding: 10px;
}
これにより、以下のような表示になります。

この基本的な実装でも十分機能しますが、JavaScriptを使用することで、アニメーションやより複雑な動作を追加できます。
JavaScriptでアニメーションをつける
<details>
と<summary>
要素は、JavaScriptを使用せずとも基本的な機能を提供しますが、JavaScriptと組み合わせることでより高度な機能を実現できます。
以下は、Web Animations APIを使用してアコーディオンメニューの開閉にアニメーションを追加する例です。
See the Pen Untitled by samuraibrass (@samuraibrass) on CodePen.
// アコーディオン内のすべてのdetails要素に対してイベントリスナーを設定
document.querySelectorAll('.accordion details').forEach(details => {
// details要素のtoggleイベント(開閉状態の変更)を監視
details.addEventListener('toggle', event => {
// 現在のdetails要素内のcontent要素を取得
const content = details.querySelector('.content');
if (details.open) {
// アコーディオンが開かれた場合
const keyframes = [
{ height: '0px', opacity: 0 }, // 開始状態:高さ0、透明度0
{ height: `${content.scrollHeight}px`, opacity: 1 } // 終了状態:実際の高さ、透明度1
];
// アニメーションを実行
content.animate(keyframes, {
duration: 300, // アニメーション時間:300ミリ秒
fill: 'forwards' // アニメーション終了後も最終フレームを維持
}).onfinish = () => {
// アニメーション完了後、高さをautoに設定して内容に合わせて調整
content.style.height = 'auto';
};
} else {
// アコーディオンが閉じられた場合
const keyframes = [
{ height: `${content.scrollHeight}px`, opacity: 1 }, // 開始状態:実際の高さ、透明度1
{ height: '0px', opacity: 0 } // 終了状態:高さ0、透明度0
];
// アニメーションを実行
content.animate(keyframes, {
duration: 300, // アニメーション時間:300ミリ秒
fill: 'forwards' // アニメーション終了後も最終フレームを維持
}).onfinish = () => {
// アニメーション完了後、height指定を削除
// これにより、ページ内検索時にコンテンツが表示可能になる
content.style.height = '';
};
}
});
});
アコーディオンの実践的なコード例とデモ
ここからはよくあるアコーディオンの実例を紹介していきます。
プラスとマイナスアイコンがありCSSで実装する場合
アコーディオンによくあるプラス・マイナスアイコンをCSSで配置する例です。
See the Pen accordion-plus-minus by samuraibrass (@samuraibrass) on CodePen.
排他的なアコーディオンの場合(一つしか開けない版)
排他的アコーディオンというのは、常にひとつしか開けない状態で複数展開ができないものです。
See the Pen Untitled by samuraibrass (@samuraibrass) on CodePen.
画像アイコンのアコーディオンの場合(SVG)
クリックによって変化するアイコンがCSSじゃなく、画像(SVG)の場合の例です。よくあるのはアローアイコンやプラス・マイナスアイコンかと思います。
See the Pen accordion-svg by samuraibrass (@samuraibrass) on CodePen.
アコーディオンのアクセシビリティ解説【中級者向け】
わかりやすさ重視のためにあえてここまで説明しませんでしたが、ここからは<div>
要素を使用した従来の方法と、
<details>
および<summary>
要素を使用した新しい方法の違いを詳しく解説し、
なぜ後者がアクセシビリティの観点から優れているかを説明します。
<div>
要素を使用した場合の問題点
従来、アコーディオンメニューは<div>
要素とJavaScriptを組み合わせて実装されることが多かったです。例えば、
<div class="accordion">
<div class="accordion-header">セクション1</div>
<div class="accordion-content">
<p>セクション1の詳細内容がここに入ります。</p>
</div>
</div>
この方法には以下のような問題があります。
- セマンティクスの欠如:
<div>
要素は意味を持たない汎用的なコンテナ要素です。そのため、スクリーンリーダーなどの支援技術は、これがアコーディオンメニューであることを理解できません。 - キーボードアクセシビリティの不足: デフォルトでは、
<div>
要素はフォーカス可能ではありません。そのため、キーボード操作でアコーディオンを開閉することができません。 - 状態の不明確さ: アコーディオンが開いているか閉じているかの状態が、HTMLの構造からは判断できません。
これらの問題を解決するには、大量のJavaScriptとARIA属性を追加する必要があり、実装が複雑になりがちです。
<details>
と<summary>
要素を使用した場合の利点
一方、<details>
と<summary>
要素を使用すると、これらの問題が自然に解決されます:
<details>
<summary>セクション1</summary>
<p>セクション1の詳細内容がここに入ります。</p>
</details>
この方法の利点は以下の通りです。
- セマンティクスの明確さ:
<details>
と<summary>
要素は、折りたたみ可能なコンテンツを表すためのセマンティックな要素です。支援技術はこれらの要素を適切に解釈し、ユーザーに正しく情報を伝えることができます。 - ネイティブのキーボードサポート: ブラウザは自動的にこれらの要素にキーボードアクセシビリティを提供します。ユーザーはTabキーで
<summary>
要素にフォーカスを移動し、Enterキーやスペースキーで開閉操作を行うことができます。 - 状態の明確な表現:
<details>
要素のopen
属性の有無で、アコーディオンの開閉状態が明確に表現されます。これにより、支援技術は現在の状態を正確にユーザーに伝えることができます。 - JavaScriptなしでの動作: 基本的な機能はJavaScriptなしで動作するため、JavaScriptが無効な環境でもアコーディオンメニューが機能します。
私はよくキーボードのみでwebサイトが見れるかをチェックするので、「❷キーボードサポート」は特に気をつけていますね。
よくある質問と解決策
Q: デフォルトで開いた状態にするには?
A: <details>
要素にopen
属性を追加することで、初期状態で開いた状態にできます。
Q: アコーディオンはaタグやbuttonタグでも良くない?
A: aやbuttonタグの場合、アコーディオンの機能を実現するには、追加のARIA属性(例:aria-expanded
)やJavaScriptが必要になる場合があります。
また、意味論的に正確で、ブラウザや支援技術に対してコンテンツの構造を明確に伝えますし、
折りたたまれたコンテンツも適切にインデックスされます。
アクセシビリティ対応のお手軽さという意味では、details/summaryタグは有用です。
まとめ
<details>
と<summary>
要素を使用したアコーディオンメニューは、アクセシビリティとパフォーマンスの両面で優れた選択肢です。
これまでaタグやbuttonなどを使用した場合に煩雑だったアクセシビリティ対応は、<details>
と<summary>
要素でデフォルトで大体対応してくれます。
Webアクセシビリティへの対応は各社これらどんどん進んでくるかと思いますので、是非このタイミングで覚えておきましょう!!
他にも私が出しているコーディング課題だと、フォームのアクセシビリティもチェックポイントになるので、自信のない人は確認しておくといいかと思います。
また、今回のアコーディオンは「【中級】デザインカンプからのコーディング実践演習」で練習することができます。
また、基本的なJavaScriptを基礎から学び直したい場合は以下の記事がおすすめです。
HTML初心者からWordPress実案件レベルまでのコーディング演習課題を「専用ページ」にて公開しています。

- Figma,Photoshopデザインからのコーディング
- サーバーアップロードでサイト公開
- プロによる最大3回の表示確認特典
- レビュー返しは爆速
- 2024年にデザイン刷新!被らないポートフォリオ
「初級編」は初めてデザインからコーディングする方向け
「中級編」はJavaScriptやjQueryの練習
「上級編」はWordPressの実案件を模擬体験できるレベル感にしています。
中級者の方には高難易度課題を詰め合わせた「即戦力セット」も出しています。
全課題で「実務レベルの、プロの厳しいレビュー」を受けられるようにしています。
また、2024年には随時デザインの刷新をしており、完全リニューアル!!
他者と差をつけられるポートフォリオが準備できます!

制作会社も使用する専用レビューツールで分かりやすく添削していきます!
基本的に「まとめて購入」していただくとかなりお得になります↓

コーディングは書籍だけではなかなか実力がつかないので、実務レベルのレビューを受けて自身をつけたい人は是非挑戦してみてください!

\課題の購入はこちらから/
ご寄付を頂けると今後の更新の励みになります!