HTMLタグ<details>でアコーディオンを作る(簡易版)

こんにちは、ナカムラです。
今回はdetailsについて試してみたものをご紹介したいと思います。

よくある質問などでよくアコーディオンを使うと思います。
たくさんある中でユーザーが求めている物・そうでないものがあるので、必要な時だけ開くようにするのが目的です。

そんなアコーディオンの作り方は色々ありまして、JavaScriptで開閉させるものと、CSSだけで制御するものなどが主流でした。
私も上記のどちらかを使っています。

detailsを活用したいと思っていますが、実務で使う場合は開閉する際にアニメーションをつけたいので結局従来のやり方で作ってしまっています。

簡単にアニメーションをつける方法がないものか模索中です。

detailsとは?

HTMLの「詳細折りたたみ要素」をマークアップするタグです。 developer.mozilla.org

<details>
    <summary>見出し</summary>
    折り畳まれる詳細
</details>

これだけでアコーディオンになります。
とても簡単ですが、そのままではアニメーションはつきません。

DEMO

実際に見てみましょう。
書いたのは下記の4種類になります。

  • HTMLだけの状態
  • HTMLだけの状態:最初から開いた状態にする
  • 開くときにアニメーションする:CSSのみ
  • 開くときにアニメーションする:JavaScriptを使用

See the Pen jsもinputもいらないHTMLタグだけのアコーディオン<details> by Nakamura (@takayo-nakamura) on CodePen.

HTMLだけの状態

まずはHTMLの状態です。
見出しの背景にはアニメーションをつけているので動いている風に見えますが、折り畳まれた詳細はただの表示・非表示になります。
詳細が1〜2行程度のコンテンツならこれで十分かもしれません。

HTMLだけの状態:最初から開いた状態にする

ページを表示したときに表示した状態にしておきたい場合もあります。
detailsにopenをつけておけばOKです。

開くときにアニメーションする:CSSのみ

開かれた時はopen属性がつくので、それを利用して装飾などの変化をつけることができます。
しかし、何度かクリックを繰り返すとアニメーションしないタイミングも出てきてしまいます。

開くときにアニメーションする:JavaScriptを使用

ステータスのタイミングの問題ならば、自分でつけてしまえ。
ということでJavaScriptに頼りました。ちょっと悔しい…。
今回はリファレンスにあるtoggleを使いました。

const animationItem = document.querySelector('.js-animation')
animationItem.addEventListener("toggle", (event) => {
  if (animationItem.open) { 
    animationItem.classList.add('is-open')
  } else {
    animationItem.classList.remove('is-open')
  }
});

要素を取得して、変化したとき(toggle)にopenかどうかで判定しています。
あとはステータスを表すクラスを付け外し、それを対象にスタイルを付けます。(スタイル自体はCSSのみの時と同じです)

最後に

気づいた方もいるかと思いますが、今回作ったアニメーションはスライドではありません。
detailsの表示/非表示は要素の表示/非表示になるため、高さの変化をつけるにはJavaScriptであらかじめ要素の高さを取得し、付与する必要があります。
閉じるときにもアニメーションをつけたい場合もJavaScriptで制御します。

スライドするアニメーションについて詳しく書いてくださっている記事がありますので、こちらをお読みください。
detailsとsummaryタグで作るアコーディオンUI - アニメーションのより良い実装方法 - ICS MEDIA