Webパーツ辞典

アコーディオンAccordion

見出しを押すと下の中身が開く部品。閉じているときは見出しだけになり、場所を取らない。

表示例

送料はいくらですか?
全国一律 550円です。5,000円以上で無料になります。
返品はできますか?
到着から7日以内であれば承ります。

別名・英語表記

  • 折りたたみ
  • 開閉パネル
  • トグルリスト
  • アコーディオンメニュー
  • ひらくとでてくる
  • クリックで開く
  • ディスクロージャー
  • Disclosure
  • Collapsible
  • Collapse
  • Details
  • Accordion

実装例

<div class="x-accordion">
  <details class="x-accordion__i" open>
    <summary class="x-accordion__s">送料はいくらですか?</summary>
    <div class="x-accordion__b">全国一律 550円です。5,000円以上で無料になります。</div>
  </details>
  <details class="x-accordion__i">
    <summary class="x-accordion__s">返品はできますか?</summary>
    <div class="x-accordion__b">到着から7日以内であれば承ります。</div>
  </details>
</div>

AIへの指示文

「アコーディオン(Accordion)」を実装してください。

## これは何か
見出しを押すと下の中身が開く部品。閉じているときは見出しだけになり、場所を取らない。

## 使いどころ
- よくある質問のように、見出しを読んで必要なものだけ開かせたいとき
- 補足情報を、じゃまにならない形で置いておきたいとき

## 実装の要件
- details > summary が最短。独自実装なら button[aria-expanded] + 中身の id
- 複数を同時に開けるか、1つだけかを決めておく
- details で1つだけ開く作りにするなら、その組の details すべてに同じ name を付ける。ブラウザが他を閉じるので、閉じる JavaScript は書かない(Chrome・Edge は 120 から、Safari は 17.2 から、Firefox は 130 から。古い環境では name が無視されて複数開くだけで、中身は読める)
- 初めから open を付けるのは、同じ name の組の中で1つまでにする
- details の開閉を動かすなら、::details-content を height: 0 と overflow: clip で閉じ、[open]::details-content を height: auto にする(::details-content は Chrome・Edge は 131 から、Safari は 18.4 から、Firefox は 143 から)
- height と content-visibility に同じ長さの transition を掛け、content-visibility には allow-discrete を付ける(抜くと閉じるときに中身が即座に消える)
- 0 から auto への補間は、details か部品の外枠に interpolate-size: allow-keywords を置いて有効にする(Chrome・Edge は 129 から。Safari・Firefox は未対応)。継承されて ::details-content にも効くので、:root に置いてページ全体の動きまで変えない
- 未対応のブラウザでは動かずに開閉するだけなので、高さを JavaScript で測って補わない
- 本文の主役を畳まない。開かないと読めない情報は、読まれないものとして扱われる
- 検索エンジンは閉じた中身も読むが、利用者は読まない。重要な内容を隠す口実にしない
- すべて開いたときの高さを確認する。画面が飛んでどこを見ていたか分からなくなることがある

## アクセシビリティの要件
- details / summary を使えば、開閉とキーボード操作はブラウザが面倒を見る
- 独自実装にするなら button + aria-expanded + aria-controls で作る
- 独自実装では、見出し要素(h3 など)の中に button を置く(h3 > button の順。button の中に見出しを入れない)。details で作るときは summary の中に button を入れない。div に onclick を付けない
- 開閉の動きは prefers-reduced-motion のときに止める
- 独自実装で閉じた中身は hidden="until-found" で隠す(details の中には付けない。付けると summary で開いても中身が見えない)。ページ内検索やページ内リンクで見つかるとブラウザが開くので、beforematch イベントでボタンを押したときと同じ開く処理を呼び、aria-expanded を true にする
- hidden="until-found" を付けた要素の display と content-visibility は変えない。none・contents・inline では検索で開かず、block などにすると未対応のブラウザで閉じても中身が見える
- リセット CSS の [hidden] { display: none; } が当たると検索で開かない。その規則は [hidden]:not([hidden="until-found"]) に絞る
- 余白と枠は hidden="until-found" を付けた要素ではなく、内側の要素に付ける。付けた要素自身の余白と枠は、閉じていても描かれる
- hidden="until-found" は Chrome・Edge は 102 から、Firefox は 148 から対応。Safari 26.2 以降と Firefox 139〜147 は開くが、一致した文字までスクロールしない。未対応のブラウザでは普通の hidden として隠れる

## 参考にする実装
この形を出発点にして、プロジェクトの命名規則・色・余白に合わせて調整してください。

```html
<div class="x-accordion">
  <details class="x-accordion__i" open>
    <summary class="x-accordion__s">送料はいくらですか?</summary>
    <div class="x-accordion__b">全国一律 550円です。5,000円以上で無料になります。</div>
  </details>
  <details class="x-accordion__i">
    <summary class="x-accordion__s">返品はできますか?</summary>
    <div class="x-accordion__b">到着から7日以内であれば承ります。</div>
  </details>
</div>
```

```css
/* 貼った先のリセットに頼らないよう、この部品の中だけ border-box にする */
.x-accordion,
.x-accordion *:not([class*="fa-"]),
.x-accordion *:not([class*="fa-"])::before,
.x-accordion *:not([class*="fa-"])::after {
  box-sizing: border-box;
  /* 貼った先の既定の書体に引きずられないようにする。書体が変わると
     文字の幅と高さが変わり、枠のサイズまでずれる */
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Noto Sans JP", "Yu Gothic UI", Meiryo, sans-serif;
}

.x-accordion {
  width: 258px;
  border: 1px solid #e3e6ea;
  border-radius: 8px;
  background: #fff;
  overflow: hidden;
}
.x-accordion__i + .x-accordion__i {
  border-top: 1px solid #e3e6ea;
}
.x-accordion__s {
  padding: 10px 14px;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}
.x-accordion__s:focus-visible {
  outline: 2px solid #1d4ed8;
  outline-offset: -2px;
}
.x-accordion__b {
  padding: 0 14px 12px;
  font-size: 11.5px;
  line-height: 1.75;
  color: #606a7b;
}
```

## 出力の約束
- HTML と CSS を分けて出す。JavaScript が要るときは素の JavaScript で書き、UIフレームワークは使わない。
- 参考実装がアイコンに Font Awesome のクラスを使っている場合は、プロジェクトで使っているアイコンかインライン SVG に置き換えてよい。
- 上のアクセシビリティ要件を満たす。満たせない箇所があるときは、理由を添えて先に知らせる。
- 色・角丸・余白は既存のデザイントークンがあればそれを使う。無ければ CSS 変数として切り出す。

使いどころ

  • よくある質問のように、見出しを読んで必要なものだけ開かせたいとき
  • 補足情報を、じゃまにならない形で置いておきたいとき

注意点

  • 本文の主役を畳まない。開かないと読めない情報は、読まれないものとして扱われる
  • 検索エンジンは閉じた中身も読むが、利用者は読まない。重要な内容を隠す口実にしない
  • すべて開いたときの高さを確認する。画面が飛んでどこを見ていたか分からなくなることがある

アクセシビリティの要点

  • details / summary を使えば、開閉とキーボード操作はブラウザが面倒を見る
  • 独自実装にするなら button + aria-expanded + aria-controls で作る
  • 独自実装では、見出し要素(h3 など)の中に button を置く(h3 > button の順。button の中に見出しを入れない)。details で作るときは summary の中に button を入れない。div に onclick を付けない
  • 開閉の動きは prefers-reduced-motion のときに止める
  • 独自実装で閉じた中身は hidden="until-found" で隠す(details の中には付けない。付けると summary で開いても中身が見えない)。ページ内検索やページ内リンクで見つかるとブラウザが開くので、beforematch イベントでボタンを押したときと同じ開く処理を呼び、aria-expanded を true にする
  • hidden="until-found" を付けた要素の display と content-visibility は変えない。none・contents・inline では検索で開かず、block などにすると未対応のブラウザで閉じても中身が見える
  • リセット CSS の [hidden] { display: none; } が当たると検索で開かない。その規則は [hidden]:not([hidden="until-found"]) に絞る
  • 余白と枠は hidden="until-found" を付けた要素ではなく、内側の要素に付ける。付けた要素自身の余白と枠は、閉じていても描かれる
  • hidden="until-found" は Chrome・Edge は 102 から、Firefox は 148 から対応。Safari 26.2 以降と Firefox 139〜147 は開くが、一致した文字までスクロールしない。未対応のブラウザでは普通の hidden として隠れる

作るときに使えるツール

見分け方

関連するパーツ