【JS不要】CSSだけでdetails要素を開閉アニメーションさせる方法

従来、details要素のなめらかな開閉アニメーションは、JavaScriptなしでは難しいものでした。

しかし、::details-content擬似要素が主要ブラウザでサポートされたことで、CSSのみで実現できるようになりました。

数ヶ月かけて完成させたJS版のdetails開閉アニメーションはお蔵入りになりそうです…。

目次

::details-content擬似要素について

::details-content擬似要素は、details要素の展開・折りたたみ可能なコンテンツを表します。

<details>
  <summary>タイトル</summary>
  <p>コンテンツ</p>
  <p>コンテンツ</p>
</details>

例えば上記のようなHTMLの場合でも、divなどのラップ不要でコンテンツ全体にスタイルをあてることができます。

details::details-content {
  background-color: skyblue;
  padding: 0 1em;
  opacity: 0;
  transition: .3s;
}

details[open]::details-content {
  padding: 1em;
  opacity: 1;
}

実装例:

タイトル

コンテンツ

コンテンツ

::details-content擬似要素は、2026年現在、最新バージョンの主要ブラウザで広くサポートされており、サポート外の環境であっても、一部のアニメーションが発生しないだけなので、実用上は問題なく利用できます。

CSS Grid版(ブラウザ対応優先)

See the Pen Details Accordion (Grid) — CSS-only by hisa (@hisaaashi) on CodePen.

::details-content擬似要素をGridコンテナとして扱い、行の高さを0frから1frへと遷移させることで開閉アニメーションを実現しています。

CSS Gridの構造上、コンテンツをラップするdiv要素が一つ必要になりますが、制御のしやすさを考えれば十分に許容できるコストです。

<details>
  <summary>...</summary>
  <div>
    <p>コンテンツ</p>
  </div>
</details>
ポイント
  • コンテンツの親にdivが必要
  • 最新の主要ブラウザであれば使える
  • CSSの指定に少しコツがいる

レンダリングのイメージ

<details>
  <summary>Details</summary>

  <!-- ブラウザが生成するコンテナ(内部にslotを持つ) -->
  <::details-content> 
      
      <!-- slotに挿入される実コンテンツ -->
      <div>
        <p>...</p>
        <p>...</p>
      </div>

  </::details-content>
</details>

デフォルトのUAスタイルシートでは、閉じた::details-contentcontent-visibility: hidden、開いた状態ではvisibleが指定されています。

この切り替えをtransitionさせるには、content-visibilityallow-discreteを指定する必要があります。

/* 開閉アニメーションの制御 */
details::details-content {
/*   content-visibility: auto; */
  display: grid;
  grid-template-rows: 0fr;
  padding-block: 0;
  transition: 
    grid-template-rows var(--d),
    padding var(--d),
    content-visibility var(--d) allow-discrete;
}

details[open]::details-content {
  grid-template-rows: 1fr;
  padding-block: 1em;
}

/* コンテンツ */
details > div {
  min-height: 0; /* ページ内検索に対応するための指定 */
  overflow: hidden;
  padding-inline: 1em;
  opacity: 0;
  transition: opacity var(--d) ease-in;
}

details[open] > div {
  opacity: 1;
}

Safariでは閉じる際にアニメーションされないバグがある

Safariでは、閉じる際にcontent-visibilitytransitionが正常に動作しないバグがあります。

これを回避するため、content-visibility: autoを追加で指定すると、閉じる際もなめらかにアニメーションできるようになります。

/* Safariで正常に動作しない */
details::details-content {
  transition-duration: .3s;
  transition-property: content-visibility;
  transition-behavior: allow-discrete;
}

/* 動作する */
details::details-content {
  content-visibility: auto;
}

ただし、この指定をすると、VoiceOverの矢印キーによって、閉じた内部のコンテンツにフォーカスできるようになってしまいます。

アクセシビリティを優先するなら、この指定はせず、バグの修正を待つ方が無難です。

ページ内検索の漏れを回避

0froverflow: hiddenの組み合わせでコンテンツを閉じてしまうと、ページ内検索でヒットしない挙動を確認しています。(2026年5月時点:Chrome)

details::details-content {
  /* 高さを0に */
  grid-template-rows: 0fr;
}

details > div {
  /* これがないと完全に閉じない */
  overflow: hidden;
}

試しにdiv要素に対しmin-height: 1pxで少し高さを確保してあげると、期待通りページ内検索にヒットするようになりました。

details > div {
  overflow: hidden;
  /* 以下を追加 */
  min-height: 1px;
  margin-top: -1px;
}

検証を重ねた結果、min-height: 0でもうまく動作していたので、こちらの追加指定が正解のようです。

details > div {
  min-height: 0; /* ページ内検索に対応するための指定 */
}

結果として、CSS Gridで開閉を行う実装では、以下の2点が「安定した折りたたみ挙動の鍵」となりそうです。

  • grid-template-rows: 0fr(高さ制御)
  • min-height: 0(最小サイズ制約の解除)

interpolate-size版(将来の標準)

See the Pen Details Accordion (allow-keywords) — CSS-only by hisa (@hisaaashi) on CodePen.

もう一つのアプローチは、root要素にinterpolate-size: allow-keywordsを指定する方法で、これまで不可能だった「高さ0からautoへのアニメーション」が可能になります。

:root {
  interpolate-size: allow-keywords;
}

details::details-content {
  overflow: hidden;
  height: 0;
  padding: 0 1em;
  opacity: 0;
  transition-duration: .3s;
  transition-property: height, padding, opacity, content-visibility;
  transition-behavior: allow-discrete;
}

details[open]::details-content {
  height: auto;
  padding-block: 1em;
  opacity: 1;
}

ただ、2026年5月現在はまだ Safari や Firefox が未対応、かつ今後のサポート時期も明示されていません。

とはいえ、非対応環境であってもheightに対するアニメーションが省略されるだけなので、「開閉さえできれば実用上の問題はない」と割り切れるのであれば、採用するのもありです。

ポイント
  • 最低限のHTMLで良い(div不要)
  • 使える環境が限られている
  • CSSが超シンプル

どちらが良いか

個人的には、現時点ではCSS Gridを使う方法がベストだと考えています。

実装コストは決して高くありませんし、比較的古いブラウザでもアニメーションが担保されるため、実務において安心して採用できるのが大きな強みです。

一方、interpolate-size は非常に魅力的ですが、サポート時期が不透明な現状では、普及したとしても実案件で気兼ねなく使えるようになるまでには、まだ時間がかかるでしょう。

いずれにせよ、JavaScriptを使わなくて済むのが本当に嬉しい。

カスタマイズに困ったらお気軽にご相談を!

  • 「ちょっとしたCSSの調整だけお願いしたい」
  • 「不具合を直してほしい」

料金は3,000円〜、お支払いは銀行振込・Amazonギフトカードなど柔軟に対応してます🤔

役に立ったら他の方にシェア

お気軽にコメントどうぞ

コメントする

目次