WithCodeMedia-1-pc
previous arrowprevious arrow
next arrownext arrow

WithCodeMedia-1-sp
previous arrowprevious arrow
next arrownext arrow

details・summary完全ガイド|JavaScriptなしでアクセシブルなアコーディオンUI実装

生徒

クライアントからアコーディオンUIを実装してほしいと言われたんですが、アクセシビリティ対応が必須らしくて…。jQueryプラグインだと対応が不十分みたいで困ってます!

ペン博士

それなら朗報じゃ!HTMLのdetails・summaryタグを使えば、JavaScriptなしで完全にアクセシブルなアコーディオンが作れるぞい。WCAG準拠で、スクリーンリーダーにもバッチリ対応じゃ!

生徒

そういう方法があるんですね!ぜひ教えてください!

Web制作の現場で、以下のような悩みを抱えていませんか?

  • アコーディオンUIのアクセシビリティ対応が複雑すぎる
  • jQueryプラグインはWCAG準拠が不透明で不安
  • キーボード操作やスクリーンリーダー対応を自前で実装するのは大変
  • JavaScript無効環境でも機能するアコーディオンが必要
  • シンプルなHTMLで実装したいが、見た目やアニメーションも欲しい

本記事では、HTMLのdetails・summaryタグを活用して、JavaScriptなしでアクセシビリティに完全対応したアコーディオンUIを実装する方法を徹底解説します。

この記事を読めば、基本的なHTML実装から、スムーズなアニメーション、ブラウザ互換性対応、実践的なトラブルシューティングまで、プロフェッショナルなアコーディオン実装が身につきます。

「学習→収入」につなげた受講生のリアルな体験談も公開中!
働き方を変えたい方にも響くストーリーです。

O.Yさん
子育てと両立できる働き方を目指し、プログラミングの学習を開始する。独学での学習に限界を感じ、WithCodeの副業コースの受講を決意。最終目標から逆算した学習計画のもとスキルを習得し、卒業後に初案件を担当。現在は実案件サポートのもと、複数案件を担当している。

詳しくはこちらの記事をご覧ください。

O.Yさんの主な制作実績はこちら


目次

なぜ今、details・summaryタグなのか?

従来のアコーディオン実装の課題

これまで、アコーディオンUIを実装する場合、以下のような方法が一般的でした:

  1. jQueryプラグイン: slideToggle()を使った実装
  2. チェックボックスハック: と:checked疑似クラスを利用
  3. カスタムJavaScript: ボタンとdiv要素を組み合わせた独自実装

しかし、これらの方法には共通の問題がありました:

実装方法課題アクセシビリティ対応
jQueryプラグインライブラリ依存、メンテナンスコスト高△(プラグイン次第)
チェックボックスハックセマンティックでない、意図不明確×(スクリーンリーダー誤認識)
カスタムJSARIA属性の手動管理が必須、実装複雑○(正しく実装すれば可能)
details/summaryなし(HTML標準)◎(ネイティブ対応)

details・summaryタグがもたらす効果

  • JavaScriptなしで動作: ネイティブ機能で開閉制御
  • 完全なアクセシビリティ対応: WCAG 2.1 レベルAA準拠
  • キーボード操作完全対応: Tab、Enter、Spaceキーで操作可能
  • スクリーンリーダー対応: 開閉状態を自動読み上げ
  • セマンティックHTML: 要素の意図が明確
  • 検索エンジン最適化: 折りたたみ内容も検索対象

アクセシビリティが重要な理由

世界保健機関(WHO)によると、世界人口の約15%(13億人)が何らかの障害を持っているとされています。また、日本では:

  • 視覚障害者:約31万人
  • 肢体不自由者(キーボードのみ操作):約177万人
  • 高齢者(65歳以上):約3,640万人(加齢による視力低下・運動機能低下)

さらに、法的要件として:

  • 障害者差別解消法(2016年施行、2024年改正): 民間事業者に合理的配慮を義務化
  • みんなの公共サイト運用ガイドライン: 公共機関サイトはWCAG 2.1レベルAA準拠が必須
  • 企業のCSR(社会的責任): アクセシビリティ対応が企業評価に直結

アクセシビリティは「特別な配慮」ではなく、「すべてのユーザーに対する基本的な配慮」です。details・summaryタグを使えば、追加コストなくこれを実現できます。


details・summaryタグの基本構造

生徒

details・summaryタグの基本構造を知りたいです!

ペン博士

うむ。意外とシンプルじゃ。ここでは、details・summaryタグの基本構造について解説するぞ!

最小限のHTML構造

アコーディオンを実装するために必要なHTMLはわずか2つのタグだけです:

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.

各要素の役割

  • ▶︎をクリックすると「詳細コンテンツ」が表示される
  • その他のコンテンツ: details・summary以外の子要素はすべて折りたたみ対象

デフォルト動作の仕様

操作動作
クリック▶︎をクリックすると開閉トグル
Enter/Spaceキーボードで開閉トグル(フォーカス時)
Tab▶︎にフォーカス移動(他の要素と同じ挙動)
開状態
属性が付与される
閉状態open属性が削除される

実際の表示例

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.


段階的な実装ガイド

生徒

details・summaryタグの実装方法を教えてください!

ペン博士

うむ。いい心がけじゃ!details・summaryタグの実装は、主に3つのレベルに分けて段階的に習得できる。ここでは、段階的な実装方法を紹介するぞ!

【レベル1】最小限の実装(JavaScript不要)

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.

実装時間:5分対応ブラウザ:すべて

このレベルで実現できること:
・クリックで開閉
・キーボード操作(Tab、Enter、Space)
・スクリーンリーダー完全対応
・JavaScript無効環境でも動作できる

【レベル2】グループ化と排他制御

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.

実装時間:10分対応ブラウザ:Chrome 120+, Edge 120+, Safari 17.2+

同じ`name`属性を指定すると、1つだけが開き、他は自動で閉じる「排他制御」が実現します:

動作: 質問1を開くと、質問2・3が自動で閉じます。

ブラウザ互換性対応(Polyfill)

古いブラウザ(Firefox 127以前、Safari 17.2以前)では、JavaScriptで排他制御を実装します:

// 排他制御のPolyfill
document.querySelectorAll('details[name]').forEach((targetDetail) => {
  targetDetail.addEventListener('toggle', () => {
    if (targetDetail.open) {
      const name = targetDetail.getAttribute('name');
      document.querySelectorAll(`details[name="${name}"]`).forEach((detail) => {
        if (detail !== targetDetail) {
          detail.removeAttribute('open');
        }
      });
    }
  });
});

【レベル3】スタイリング(CSS)

実装時間:30分対応ブラウザ:すべて

デフォルトスタイルのリセット

ブラウザが表示するデフォルトの三角形アイコンを削除します:

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.

カスタムアイコンの追加

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.

コンテンツエリアのスタイリング

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.


アニメーション実装の完全ガイド

生徒

details・summaryタグのアニメーションの実装方法も知りたいです!

ペン博士

うむ。details・summaryタグの唯一の弱点は、デフォルトではアニメーションがないことじゃ。ここでは、スムーズなアニメーション実装方法を紹介するぞ!

方法1: CSSアニメーション(最新ブラウザ対応)

対応ブラウザ:Chrome 123+, Edge 123+(Safari、Firefoxは2026年1月時点で未対応)

最新のCSS仕様 `::details-content` 疑似要素を使用します:

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.

注意点: Safari/Firefoxでは動作しないため、後述のJavaScript方式が推奨です。

方法2: JavaScriptアニメーション(全ブラウザ対応)

対応ブラウザ:すべて(IE11以外)

Web Animations APIを使用した実装です。最も信頼性が高く、推奨される方法です。

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.

ポイント: コンテンツを2重divで囲むことで、paddingを保持したままheightアニメーションが可能になります。

コードのポイント解説

ポイント説明
e.preventDefault()ブラウザのデフォルト開閉動作を無効化し、カスタムアニメーションを実行
isClosing / isExpanding連打防止フラグ。アニメーション中は新しい操作を無視
offsetHeight要素の実際の高さを取得。auto値は使えないため動的に取得
animate()Web Animations API。jQueryのanimate()より軽量で高速
onfinishアニメーション完了時の処理。フラグをリセット

コピペで使える実践コード集

生徒

他にも様々な実装方法を知りたいです!

ペン博士

おう!さらに興味を持ってくれて何よりじゃ!ここでは、実際のプロジェクトでそのまま使える、完成度の高いコード例を紹介するぞ!

パターン1: シンプルなFAQ

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.

パターン2: カード型アコーディオン

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.

パターン3: ネストされたアコーディオン

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.


ブラウザ互換性と対応表

details・summaryタグの対応状況

ブラウザ基本機能name属性(排他制御)::details-content
Chrome12+ 120+ 123+
Edge79+ 120+ 123+
Safari6+ 17.2+ 未対応
Firefox49+ 127+ 未対応
Opera15+ 106+ 109+
iOS Safari6+ 17.2+ 未対応
Android Chrome4.0+ 120+ 123+

推奨実装パターン

要件推奨実装理由
基本的なアコーディオンHTMLのみすべてのブラウザで動作、軽量
排他制御HTML(name属性)+ JavaScript Polyfillモダンブラウザはネイティブ、古いブラウザはJS
アニメーションJavaScript(Web Animations API)全ブラウザ対応、細かい制御可能
IE11対応jQueryプラグインdetails/summaryは非対応のため代替実装

トラブルシューティング

生徒

details・summaryを使用するにあたってトラブルシューティングのことも知りたいです!

ペン博士

うむ。ここでは、主なトラブルシューティングを5つ紹介するぞい!

問題1: アニメーションがカクつく

原因: アニメーション中に連続クリックすると、複数のアニメーションが競合

解決策: アニメーション中はクリックを無視する

onClick(e) {
  e.preventDefault();

  // アニメーション中は無視
  if (this.isClosing || this.isExpanding) {
    return;
  }

  // 開閉処理
}

問題2: Safariでアイコンが消えない

原因: Safariは::-webkit-details-markerだけでは不十分

解決策: list-styleも合わせて指定

summary {
  list-style: none; /* Firefox用 */
}

summary::-webkit-details-marker {
  display: none; /* Chrome, Safari用 */
}

/* Safariで確実に消すための追加指定 */
summary::marker {
  display: none;
}

問題3: padding付きでアニメーションがズレる

原因: heightアニメーションはpaddingを含まない

解決策: 2重divで囲み、内側にpaddingを指定

See the Pen Untitled by せいや (@ddwkeakz-the-reactor) on CodePen.

問題4: スクリーンリーダーで読み上げ順序が不自然

原因: 複雑なHTMLネスト構造

解決策: シンプルな構造を保ち、不要な要素は削除する

<!-- 悪い例 -->
<details>
  <div>
    <div>
      <summary>見出し</summary>
    </div>
  </div>
  <p>コンテンツ</p>
</details>

<!-- 良い例 -->
<details>
  <summary>見出し</summary>
  <p>コンテンツ</p>
</details>

問題5: モバイルでタップ反応が遅い

原因: モバイルブラウザの300msクリック遅延

解決策: touch-action: manipulationを指定

summary {
  touch-action: manipulation; /* ダブルタップズーム無効化 */
  cursor: pointer;
}

ベストプラクティス4つのチェックリスト

生徒

details・summaryをうまく実装するためにはどうしたら良いですか?

ペン博士

良い質問じゃ。ここでは、プロフェッショナルな実装をするための4つの項目を紹介するぞ!

1. アクセシビリティ

  • フォーカス表示: summary:focusで視覚的なフィードバック
  • 色だけに依存しない: アイコンや形状でも状態を示す
  • コントラスト比: WCAG AAレベル(4.5:1以上)を満たす

2. パフォーマンス

  • 連打対策: アニメーション中のクリックを無視
  • リフロー最小化: `transform`を優先、`height`は最小限
  • will-change回避: 過度な使用はメモリ消費増加

3. ユーザビリティ

  • タップ領域: 最低44x44pxを確保(モバイル対応)
  • 視覚的フィードバック: ホバー時の色変化
  • 状態の明示: 開閉状態が一目でわかるアイコン

4. SEO

  • 構造化データ: FAQならFAQPage schemaを実装
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [{
    "@type": "Question",
    "name": "送料はかかりますか?",
    "acceptedAnswer": {
      "@type": "Answer",
      "text": "5,000円以上のご購入で送料無料です。"
    }
  }]
}
</script>

よくある質問(FAQ)

Q1: details・summaryタグはすべてのブラウザで使えますか?

A: はい、モダンブラウザでは完全サポートされています。Chrome 12+、Firefox 49+、Safari 6+、Edge 79+で動作します。IE11は非対応のため、Polyfillまたは代替実装が必要です。

Q2: JavaScriptなしでアニメーションは可能ですか?

A: CSSの::details-content疑似要素を使えば可能ですが、Chrome 123+、Edge 123+のみ対応です。Safari、Firefoxでは未対応のため、全ブラウザ対応にはJavaScript(Web Animations API)の使用を推奨します。

Q3: アクセシビリティ対応で追加実装は必要ですか?

A: 基本的には不要です。details・summaryタグは標準でWCAG 2.1レベルAA準拠です。ただし、以下のCSS実装を推奨します:

  • フォーカス表示(`outline`)
  • コントラスト比4.5:1以上
  • タップ領域44x44px以上(モバイル)

Q4: 複数のアコーディオンで1つだけ開く排他制御は可能ですか?

A: はい、name属性を使用します。`

同じname値を指定すると、1つが開くと他が自動で閉じます。Chrome 120+、Safari 17.2+、Firefox 127+で動作。古いブラウザ向けにJavaScript Polyfillを用意してください。

Q5: デフォルトで開いた状態にできますか?

A: はい、open属性を付与します。

こうすることで、ページ読み込み時に展開状態になります。重要な情報やデフォルト表示したい内容に使用してください。

Q6: スクリーンリーダーではどう読み上げられますか?

A: summaryの内容 + 「折りたたまれています」または「展開されています」と自動読み上げされます。開閉状態の変更も自動でアナウンスされるため、ARIA属性の手動管理は不要です。NVDA、JAWS、VoiceOverで動作確認済みです。

Q7: SEO的に折りたたみコンテンツは不利ですか?

A: いいえ、details・summaryタグで折りたたまれたコンテンツも検索エンジンは完全にインデックスします。Googleは「ユーザビリティ向上のための折りたたみ」として評価します。FAQの場合は構造化データ(FAQPage schema)を追加実装することで、リッチリザルト表示も可能です。

Q8: jQueryプラグインから移行する際の注意点は?

A: 以下の点に注意してください:

  1. イベント名の変更(click→toggle)
  2. 開閉状態の取得方法(hasClass(open) → element.open)
  3. CSSセレクタの変更(.accordion.open→ details[open])

既存のカスタムイベントやコールバック処理は、toggleイベントで再実装が必要です。

Q9: モバイルでの挙動は問題ありませんか?

A: 問題ありません。ただし以下の対策を推奨します:

  1. touch-action: manipulation;でダブルタップズーム遅延を解消
  2. summaryのタップ領域を最低44x44pxに設定
  3. アニメーション速度を300〜400msに調整(モバイルは速めが好まれる)

iOS Safari、Android Chromeで動作確認必須です。

Q10: ネストされたアコーディオンは実装できますか?

A: はい、要素の中に別の要素を配置できます。親アコーディオンの開閉と子アコーディオンの開閉は独立して動作します。ただし、視覚的な階層がわかるように、インデントやボーダー色で区別することを推奨します。

Q11: アニメーション中にクリックされた場合の挙動は?

A: 連打防止策を実装していない場合、アニメーションがリセットされカクつきます。解決策として、isClosingやisExpandingフラグでアニメーション中のクリックを無視する実装を推奨します。記事内のJavaScriptコード例を参照してください。

Q12: WordPressやReactで使う場合の注意点は?

A: WordPressではGutenbergブロックとして実装可能です。Reactでは、open属性を状態管理せず、ネイティブ動作に任せるのが推奨です。制御したい場合は、useRefでDOM参照し、toggleイベントを監視してください。defaultOpenプロップでデフォルト開閉状態を設定できます。

Q13: カスタムアイコンを矢印ではなく画像にできますか?

A: はい、summary::afterに背景画像を設定できます。background-image: url(icon.svg);とし、details[open] summary::afterで別画像に切り替えます。SVGスプライトを使用すれば、HTTPリクエストを削減できます。アイコンフォント(Font Awesome等)も使用可能です。

Q14: アコーディオン開閉時にアナリティクスイベントを送信できますか?

A: はい、toggleイベントをリスニングしてトラッキングコードを実行できます:

element.addEventListener('toggle', () => {
  if (element.open) {
    gtag('event', 'accordion_open', {
      label: summaryText
    });
  }
});

Google Analytics、Adobe Analyticsなど各種ツールに対応可能です。

Q15: 印刷時にすべてのアコーディオンを展開表示できますか?

A: はい、@media printでopen属性を強制付与します:

@media print {
  details {
    display: block;
  }

  details > * {
    display: block !important;
  }
}

印刷時はすべて展開状態で出力されます。summaryは見出しとして表示され、折りたたみ機能は無効化されます。

生徒

detailsとsummaryってこんなに便利だったんですね!これからFAQとかを作るときに使ってみます!

ペン博士

じゃろう?最近のHTMLはかなり進化しておる。
今回のdetailsとsummaryもその代表例じゃな!

生徒

ありがとうございます!とても勉強になりました!


まとめ

本記事では、HTMLのdetailsとsummaryタグを活用した、アクセシビリティに完全対応したアコーディオンUI実装を徹底解説しました。

重要なポイントは以下の通りです。

・JavaScriptなしで動作: ネイティブ機能で開閉制御、軽量で高速
・WCAG 2.1レベルAA準拠: キーボード操作、スクリーンリーダー完全対応
・3段階の実装レベル: 最小限(HTML) → グループ化 → アニメーション
・全ブラウザ対応: Web Animations APIで信頼性の高いアニメーション
・SEO最適化: 折りたたみ内容も完全インデックス、FAQPage schemaでリッチリザルト対応

WithCodeで学んだWeb制作スキルに、アクセシブルなUI実装を組み合わせれば、すべてのユーザーに優しいWebサイトを構築できます。

大切なのは、完璧を目指さず、段階的に実装することです。

  1. Week 1: 基本的なHTML実装でまず動かす
  2. Week 2: CSSでスタイリング、フォーカス表示を追加
  3. Week 3: JavaScriptでアニメーション実装
  4. Week 4: アクセシビリティ監査、実機テスト

アクセシビリティ対応は「後回しにできる要素」ではなく、最初から組み込むべき基本要件です。details・summaryタグを使えば、追加コストなくWCAG準拠のアコーディオンUIが実装できます。

クライアントプロジェクトの品質向上、そしてご自身のスキルアップのために、今日からアクセシブルなアコーディオン実装を始めましょう!


WithCodeを体験できる初級コース公開中!

初級コース(¥49,800)が完全無料に!

  • 期間:1週間
  • 学習内容:
    ロードマップ/基礎知識/環境構築/HTML/CSS/LP・ポートフォリオ作成
    → 正しい学習方法で「確かな成長」を実感できるカリキュラム

副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?

未経験でも心配することはありません。初級コースを受講される方の大多数はプログラミング未経験です。まずは無料カウンセリングで、悩みや不安をお聞かせください!

WithCodeでは、Web制作の技術だけでなく、アクセシビリティ対応やWCAG準拠の実装も学べるカリキュラムを用意しています。プロとして活躍するために必要な、技術力とユーザー配慮の両方を身につけましょう。

この記事を書いた人

WithCode(ウィズコード)は「目指すなら稼げる人材」をビジョンに、累計400名以上のフリーランスを輩出してきた超実践型プログラミングスクールです。150社以上の実案件支援を特徴にWeb制作・Webデザインなどの役立つ情報を現場のノウハウに基づいて発信していきます。

– service –WithCodeの運営サービス

  • WithCode
    - ウィズコード -

    スクール

    「未経験」から
    現場で通用する
    スキルを身に付けよう!

    詳細はこちら
  • WithFree
    - ウィズフリ -

    実案件サポート

    制作会社のサポート下で
    実務経験を積んでいこう!

    詳細はこちら
  • WithCareer
    - ウィズキャリ -

    就転職サポート

    大手エージェントのサポート下で
    キャリアアップを目指そう!

    詳細はこちら

公式サイト より
今すぐ
無料カウンセリング
予約!

目次