アコーディオンのタイトルです
ここがアコーディオンの中身です

↓自分で書いたコード

<div id="ac_wrap">
  <div id="ac_ttl">アコーディオンのタイトルです</div>
  <div id="ac_txt">ここがアコーディオンの中身です</div>
</div>

<script>
document.addEventListener("DOMContentLoaded", () => {
  const ac_ttl = document.getElementById("ac_ttl");
  const ac_txt = document.getElementById("ac_txt");

  ac_ttl.addEventListener("click", () => {
    ac_txt.classList.toggle("is-active");
    ac_ttl.classList.toggle("is-open");
  });
});
</script>

<style>
#ac_txt {
  display: none;
}

#ac_txt.is-active {
  display: block;
}
</style>

②改良版

・自分で書いたのはID取得になっていたので
複数のアコーディオンに対応していなかった。

classを取得するようにした
アコーディオン

アコーディオン1
ここが中身です。
テキストが増えてもOK
アコーディオン2
別のアコーディオンの中身です
document.addEventListener("DOMContentLoaded", () => {
①HTMLがすべて読み込まれてからJSを実行する
なぜ必要?
・JSは上から順に実行される
・HTMLがまだ無いと
→ getElement / querySelector が null になる

  document.querySelectorAll(".ac_ttl").forEach((ttl) => {
②document.querySelectorAll(".ac_ttl")
 ⇒.ac_ttl クラスが付いた すべての要素 を取得
③.forEach((ttl) => {
 ⇒取得した .ac_ttl を 1個ずつ順番に処理

    ttl.addEventListener("click", () => {
④クリックされたら中の処理を実行
const content = ttl.nextElementSibling;
⑤タイトルの次の要素 を取得
 nextElementSibling = 直後の兄弟要素
 .ac_txt を直接探さなくていい
const isOpen = ttl.classList.contains("is-open");

if (isOpen) {
content.style.height = null;
ttl.classList.remove("is-open");
⑦高さ指定を消す
      } else {
⑧もし「すでに高さが設定されている」なら
→ 高さを消して閉じる
そうでなければ
→ 中身の高さまで広げる
content.style.height = content.scrollHeight + "px";
ttl.classList.add("is-open");
⑨中身の本当の高さを取得して設定
scrollHeight =
・中に入っている全コンテンツの高さ
・テキストが増減しても自動対応
・ px を付けないと無効になるので注意
      }
    });
  });
});