webサイトでアコーディオンメニューは良く見る機能です。
世の中には様々なライブラリやUIフレームワークがあり、アコーディオンという機能もわざわざ自力実装せずとも使えるわけですが…
「デザインに自由度が欲しい」などの理由で自力実装せざるを得ない場合が存在します。
先日、自力実装したので記録を残しておこうと思います。
JavaScript で実装するとして、
- クリックイベントから処理を発火させる。
- アコーディオンの開閉要素を style で設定。
- 閉じるときは0。
- 開くときは要素の高さ。
- CSSでアニメーションを付ける。
のような感じかと思います。
そしてよくある悩みどころとしては
「サイズは可変にしたいけど、高さをautoにしたらCSSのtransitionが効かない」
があるのではないでしょうか。
対策としては、
- アニメーションに animate を使う。
- transition 完了後に auto を指定する。
- autoを使わずに、都度再計算する。
あたりでしょうか。
自分は今回3を選びました。1か2の方がスマートっぽいのに何故3を選んだかというと
- アコーディオンを配置した親要素が非表示になった上で、サイズが変わった時にも表示が崩れない。
- アコーディオンを入れ子で使える。
といった条件を解決するためです。(実は1か2でも解決方法があるかもしれませんが)
上記の条件を解決するために、MutationObserver と ResizeObserver を使いました。
「MutationObserver と ResizeObserver でDOMの変化を検知して都度アコーディオンの高さを計算する」
めんどくさいですね。汎用的な機能にしようとすると、アコーディオンに限らず自力実装は大体めんどうです。ライブラリやUIフレームワークで解決できるならするに越した事はありません。
しかし、やってみるとDOM操作について学びになるのでたまにはやってみると良いかもしれません。あまりスマートにかけたという気もしないので(なのでコードは載せない)自分でもいつかリベンジすると思います。