1. ホーム
  2. HTML

【HTML】details・summary でアコーディオン(開閉メニュー)を作る方法

Share

クリックすると中身が開いたり閉じたりする「アコーディオン」や、よくある質問(FAQ)の開閉メニュー。これらは JavaScript を書かなくても、HTML の <details><summary> という2つのタグだけで作れます。この記事では、基本の書き方から、初期表示を開いた状態にする open 属性、複数並べた FAQ の作り方、CSS で三角マーカーや見た目を整える方法までを、実際に開閉できるデモつきで解説します。

details と summary でできること

<details> は、ふだんは隠れていて、クリックすると中身が開く「折りたたみ可能なエリア」を作るタグです。そして <summary> は、その開閉ボタンを兼ねた見出し(ラベル)になります。閉じているときは <summary> の文字だけが表示され、クリックすると残りの中身がするりと開きます。

うれしいのは、この開閉の動きをブラウザがすべて自動で処理してくれる点です。クリックされたら開く、もう一度クリックしたら閉じる、といった制御を自分で書く必要がありません。JavaScript なしで動くため、コードがシンプルになり、スクリプトが無効な環境でもきちんと開閉できます。

基本の書き方

使い方はとてもシンプルです。<details> で全体を囲み、その中のいちばん最初<summary> でラベルを書きます。<summary> より後ろに書いた内容が、開いたときに表示される中身になります。

index.html
<details>
  <summary>クリックで開く見出し</summary>
  <p>ここが開いたときに表示される中身です。</p>
</details>

これだけで、クリックで開閉する部品が完成します。中身には段落だけでなく、リストや画像、別の <details> など、好きな要素を入れられます。

summary は details の最初の子に置く

ひとつだけ守りたいルールがあります。<summary><details>最初の子要素として置くことです。先頭に書かれた <summary> がラベルとして扱われ、それ以外が開閉する中身になります。順番を逆にしたり、<summary> を途中に書いたりすると、ラベルとして正しく認識されず、表示が崩れる原因になります。

なお、<summary> を省略することもできますが、その場合は「詳細」などブラウザが用意した文言が表示されてしまいます。何の項目なのかが伝わるよう、<summary> でラベルを明記するのがおすすめです。

open 属性で最初から開いておく

<details> は標準では閉じた状態で表示されます。最初から開いた状態にしておきたいときは、open 属性を付けます。

index.html
<!-- 最初から開いた状態で表示される -->
<details open>
  <summary>最初から開いている項目</summary>
  <p>ページを開いた時点で中身が見えています。</p>
</details>

open は値を持たない属性で、付いていれば開く、書かなければ閉じる、というシンプルな指定です。注目してほしい項目や、最初に読んでほしい内容に付けておくとよいでしょう。ユーザーがクリックして開閉すると、この open 属性はブラウザによって自動で付け外しされます。後述する CSS では、この性質を利用して「開いているとき」だけのスタイルを当てられます。

FAQ・アコーディオンを作って動かしてみよう

<details> を複数並べれば、そのまま FAQ やアコーディオンメニューになります。下のデモには3つの質問を並べ、いちばん上だけ open 属性で開いた状態にしています。CSS では、デフォルトの三角マーカーを消して「+/−」の自作マーカーに置き換え、開いている項目に色を付けています。プレビュー内の見出しをクリックして、開閉の動きを確かめてみてください。

<h2 class="faq-title">よくある質問</h2>

<details class="faq" open>
  <summary>送料はいくらかかりますか?</summary>
  <p>全国一律500円です。5,000円以上のご購入で送料無料になります。</p>
</details>

<details class="faq">
  <summary>注文後、どのくらいで届きますか?</summary>
  <p>通常、ご注文から2〜4営業日でお届けします。離島の場合はもう少しお時間をいただきます。</p>
</details>

<details class="faq">
  <summary>返品・交換はできますか?</summary>
  <p>商品到着後7日以内であれば、未使用品にかぎり返品・交換を承ります。</p>
</details>
body {
  margin: 0;
  padding: 20px;
  font-family: sans-serif;
  color: #333;
  background: #f7f7fb;
}

.faq-title {
  font-size: 18px;
  margin: 0 0 16px;
}

.faq {
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 8px;
  margin-bottom: 12px;
  overflow: hidden;
}

/* summary がラベル(クリックで開閉する見出し)になる */
.faq summary {
  padding: 14px 16px;
  font-weight: bold;
  cursor: pointer;
  list-style: none; /* デフォルトの三角マーカーを消す */
}

/* WebKit 系のマーカーも消す */
.faq summary::-webkit-details-marker {
  display: none;
}

/* 自前のマーカー(+)を付ける */
.faq summary::before {
  content: "+";
  color: #4f46e5;
  margin-right: 8px;
  font-weight: bold;
}

/* 開いているときは − に切り替える */
.faq[open] summary::before {
  content: "−";
}

/* 開いているときの見出しに色を付ける */
.faq[open] summary {
  background: #eef0ff;
}

.faq p {
  margin: 0;
  padding: 0 16px 16px;
  line-height: 1.7;
}
Preview

CSS で見た目を整える

デフォルトの <details> はそっけない見た目ですが、CSS で自由に整えられます。とくに調整したくなるのが、<summary> の先頭に表示される三角マーカーです。

デフォルトの三角マーカーを消す

閉じているときに表示される ▶ のマーカーは、<summary> のリストマーカーとして描画されています。そのため list-style: none で消せます。古い Safari など WebKit 系のブラウザでは、加えて ::-webkit-details-marker 擬似要素を display: none にしておくと確実です。

style.css
summary {
  list-style: none; /* 標準の三角マーカーを消す */
  cursor: pointer;  /* クリックできることを示す */
}

/* WebKit 系のマーカーも消す */
summary::-webkit-details-marker {
  display: none;
}

マーカーを消したうえで、上のデモのように summary::before で「+」などの自作マーカーを付ければ、デザインに合わせた開閉アイコンにできます。

開いているときだけスタイルを変える

開いた状態の <details> には open 属性が付くため、属性セレクタの details[open] で「開いているときだけ」のスタイルを指定できます。背景色を変えたり、マーカーを「+」から「−」へ切り替えたりと、状態に応じた見た目を JavaScript なしで表現できます。

style.css
/* 閉じているときのマーカー */
summary::before {
  content: "+";
}

/* 開いているときだけ − に切り替える */
details[open] summary::before {
  content: "−";
}

name 属性で1つだけ開く(アコーディオン)

<details> を複数並べると、初期状態ではそれぞれが独立して開閉します。つまり、複数の項目を同時に開いておけます。一方、よくあるアコーディオンのように「1つ開くと、ほかは自動的に閉じる」動きにしたいこともあります。これを実現するのが、比較的新しく追加された name 属性です。

複数の <details>同じ nameを付けると、それらが1つのグループ(排他グループ)として扱われ、グループ内で開けるのは常に1つだけになります。ラジオボタンの name によるグループ化とよく似た仕組みです。

index.html
<!-- 同じ name でグループ化すると、開くのは常に1つだけ -->
<details name="faq">
  <summary>質問1</summary>
  <p>回答1</p>
</details>

<details name="faq">
  <summary>質問2</summary>
  <p>回答2</p>
</details>

この書き方なら、JavaScript を一切使わずに本格的なアコーディオンが作れます。主要な属性を整理すると、次のとおりです。

属性付ける要素役割
open<details>最初から開いた状態で表示する。値は不要
name<details>同じ値どうしをグループ化し、開くのを常に1つだけにする(排他開閉)

name 属性は比較的新しい機能のため、ごく古いブラウザでは排他開閉が効かず、それぞれが独立して開閉します。ただしその場合でも「開閉できる」という基本機能は問題なく動くので、安心して使えます。

まとめ

<details><summary> を使えば、JavaScript なしで開閉メニューやアコーディオン、FAQ を手軽に作れます。

  • <summary><details> の最初の子に置き、開閉ラベルにする
  • 最初から開いておきたいときは open 属性を付ける
  • マーカーは list-style: none で消し、details[open] で開いた状態のスタイルを当てる
  • 同じ name でグループ化すると、開くのを1つだけにできる

まずは <details><summary> だけのシンプルな形から書いてみて、そこに CSS や name 属性を足していくと、思いどおりの開閉メニューに仕上げられます。

参考リンク