コード (TailwindCSS v4)
See the Pen accordion by hrel11 (@hrel11) on CodePen.
コード (バニラCSS)
See the Pen accordion (vanillacss) by hrel11 (@hrel11) on CodePen.
HTML解説
本記事のアコーディオンメニューでは主にdetailsタグとsummaryタグを利用している。
たとえばChromium系ブラウザでは下図のようなDOMツリーが構成される。
2026年3月現在ブラウザによってShadow DOMの実装が微妙に異なる。
必ずしも上図と一致するわけではないことに注意
detailsタグ
HTML単体でアコーディオンメニューを構成できるタグ。
See the Pen Untitled by hrel11 (@hrel11) on CodePen.
-
open属性によりウィジェットの開閉状態を管理する-
trueで開く -
falseで閉じる(デフォルト値)
-
-
name属性により複数のdetailsタグを連動して開閉させることも可能 - detailsタグ直下には2つのShadowDOMが自動的に描画される
- summary部分の親要素(ウィジェットの開閉状態に関わらず常に表示される部分)
- contents部分の親要素(開閉で表示/非表示になるコンテンツ部分)
- summary部分の親要素ではTabキーによるフォーカスが効く。これによりEnterキーやSpaceキーで開閉操作をすることが可能
summaryタグ
ウィジェットの開閉状態に関わらず常に表示されるタグ。
See the Pen Untitled by hrel11 (@hrel11) on CodePen.
- detailsタグから生成されるShadowDOMのうち、summary部分を上書きする
::details-content
「開閉で表示/非表示になるコンテンツ部分」を示す疑似要素。
detailsタグによって自動生成される。

::details-contentの子要素にはdetailsタグの中身(summaryタグを除く)が描画される
CSS解説
マーカーのリセットCSS
summary部分にはデフォルトで左側に三角マーカー(▼)が表示されるが、このマーカーを非表示にすることも可能
<summary class="list-none marker:content-none">
見出し
<svg />
</summary>
見た目をリッチにするにはマーカー部分の表現も重要となる。
そのためにはデフォルトの三角マーカーを無効化して代わりにimg要素やsvg要素でマーカーを描画する
See the Pen remove marker by hrel11 (@hrel11) on CodePen.
groupクラスによる状態連動
detailsタグの開閉状態(open属性)に連動して子要素のスタイルを定義できる。
<details class="group">
<summary>
<svg class="group-open:rotate-180">...</svg>
</summary>
</details>
下記のコードでは開閉時にマーカーの向きが変化する。
マーカーにアニメーションを付けるならtransition-transform duration-[250ms]等を付与すればよい
See the Pen Untitled by hrel11 (@hrel11) on CodePen.
アニメーション設定
::details-contentの高さをgrid-template-rowsによって表現する。
details-content:grid
details-content:grid-rows-[0fr] /* 閉じた状態 */
open:details-content:grid-rows-[1fr] /* 開いた状態 */
トランジションについてはこれらを併用する必要がある
/* 離散値プロパティのアニメーションを非表示にさせないために必要 */
details-content:transition-[content-visibility,grid-template]
/* アニメーション時間 */
details-content:duration-[250ms]
/* 離散値プロパティをアニメーションさせるために必要 */
details-content:transition-discrete
-
content-visibilityをトランジション対象に含めることでアニメーション中に該当要素が非表示になってしまうことを防ぐ -
transition-discrete(transition-behavior: allow-discrete;) は離散値を取るプロパティを滑らかにアニメーションさせるために必要となる- 今回の事例における「離散値を取るプロパティ」は
grid-template-rows - 少なくともChromium系ブラウザではアニメーション実装のために本クラスが必須である(2026年3月現在)
- 今回の事例における「離散値を取るプロパティ」は
- これらにより
grid-template-rowsが1frから0frに変化する際にも滑らかにアニメーションすることができる
ブラウザの種別・バージョンによってはアコーディオンが閉じる際のアニメーションが効かない
(スマートフォンのSafariなど)
あらゆる環境で開閉アニメーションをさせたい場合にはJSでの実装を検討する
overflow-hiddenの役割
div要素に対してoverflow-hiddenを付与することで、::details-contentからはみ出すことがないようにする
<!-- 親要素で高さのアニメーションを実施 -->
::details-content
<!-- 子要素はグリッドレイアウトに含まれる -->
<div class="overflow-hidden">
</div>
::details-contentの高さが変動しただけではアニメーションが可視化されない。
その原因は上記div要素がグリッドレイアウトの子要素となっていることにある。
グリッドレイアウトでは min-height: auto; の解釈が「コンテンツサイズに基づく最小の高さ」に変化することで、div要素は自身の高さを維持することを優先するようになる。
そのため::details-contentのアニメーション中においてもdiv要素がアニメーションを貫通して表示されてしまう。
参考記事
- details要素を閉じる際にもCSSアニメーションを有効にする方法
- details/summaryでアコーディオンの開閉アニメーションを実装する方法
- detailsとsummaryタグで作るアコーディオンUI - アニメーションのより良い実装方法
