アコーディオン

アコーディオン
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";
    };
  });
});

Loading...