アコーディオン
JavaScript
const ACTIVE = "is-active"; // 開閉状態を示すクラス
const DURATION = 300; // アニメーション時間(ms)
document.querySelectorAll(".accordion").forEach((root) => {
// 各アコーディオン内の要素を取得
const btn = root.querySelector(".accordion-button");
const panel = root.querySelector(".accordion-content");
// 必要な要素がなければ処理しない
if (!btn || !panel) return;
// 初期状態:閉じる(高さ0にして見えなくする)
panel.style.blockSize = "0px";
panel.style.overflow = "hidden"; // はみ出し防止
btn.addEventListener("click", () => {
// クラスを切り替えて現在の状態を取得(trueなら開く)
const isOpen = panel.classList.toggle(ACTIVE);
// 現在の高さを取得(アニメーション開始位置)
const start = panel.getBoundingClientRect().height;
// 一度autoにして中身の本来の高さを取得
panel.style.blockSize = "auto";
const end = panel.getBoundingClientRect().height;
// アニメーション前に開始高さへ戻す
panel.style.blockSize = `${start}px`;
// 開く or 閉じるアニメーション
const anim = panel.animate(
[
{ blockSize: `${start}px` },
{ blockSize: `${isOpen ? end : 0}px` },
],
{
duration: DURATION,
easing: "ease",
fill: "forwards", // アニメーション後の状態を維持
}
);
// アニメーション終了後の最終状態を確定
anim.onfinish = () => {
// 開いている場合はautoに戻して可変にする
// 閉じている場合は0で固定
panel.style.blockSize = isOpen ? "auto" : "0px";
};
});
});