.classList.toggle()

JavaScriptの.classList.toggle()でアコーディオン

Javaのアコーディオン

JavaScriptの .classList.toggle() を使ってアコーディオンを作ります。

.classList.toggle()

.classList.toggle() は、classの追加・削除ができるプロパティで、名前の通り1つのスイッチでON/OFF(有効/無効)といった2つの状態の切り替えをおこなうことができます

クリックやスクロール系のイベントと一緒に使って、例えば「一定量のスクロールでclassを付与して表示」「クリックで表示・非表示のclassを追加」など、いろんな用途で使えます。

.classList.toggle()を使ったアコーディオンサンプル

早速 .classList.toggle() を使ったアコーディオンサンプルです。

あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、う

あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、う

あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、う

あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、う

至って普通のアコーディオンで、各見出し部分をクリックすると中身のコンテンツが表示・非表示で切り替わります。

アコーディオンサンプルのコード

アコーディオンのコードです。

HTMLは containeraccordion-groupaccordion の階層です。

<div class="container">
  <div class="accordion-group">
    <div class="accordion">
      <button class="accordion-header">accordion 1</button>
      <div class="accordion-panel">
        <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、う</p>
      </div>
    </div>
    <div class="accordion">
      <button class="accordion-header">accordion 2</button>
      <div class="accordion-panel">
        <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、う</p>
      </div>
    </div>
    <div class="accordion">
      <button class="accordion-header">accordion 3</button>
      <div class="accordion-panel">
        <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、う</p>
      </div>
    </div>
    <div class="accordion">
      <button class="accordion-header">accordion 4</button>
      <div class="accordion-panel">
        <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、う</p>
      </div>
    </div>
  </div>
</div>

次にJavaScriptのコードですが、accordion-header のボタンタグをクリックすると active のclassが toggle で追加され、.nextElementSibling で次の要素に show のclassを追加して表示させます。

var acc = document.getElementsByClassName("accordion-header");
var i;

for (i = 0; i < acc.length; i++) {
    acc[i].onclick = function(){
        this.classList.toggle("active");
        this.nextElementSibling.classList.toggle("show");
  }
}

.previousElementSibling .nextElementSibling

.nextElementSiblingは「指定した要素の1つ後の要素を取得」するプロパティです。ちなみに、.previousElementSiblingは「指定した要素の1つ前の要素を取得」するプロパティです。

例えば、HTMLで以下のようなリストがあったとします。

  <ul>
    <li id="list1">リスト1</li>
    <li id="list2">リスト2</li>
    <li id="list3">リスト3</li>
  </ul>

このリストに対して、それぞれElementSiblingのプロパティで取得すると以下のようになります。

const list2 = document.getElementById('list2');
console.log(list2.previousElementSibling);
// => <li id="list1">
console.log(list2.nextElementSibling);
// => <li id="list3">

このように、.previousElementSibling.nextElementSibling は、並列並びの要素がある時に使えるプロパティです。

かかかず
かかかず

この記事でのJavaScriptのコードでは、.nextElementSibling を使っています。

CSS

JavaScriptのコードは、トグルでclassの付け替えだけ行うので、アコーディオンの見た目や表示はCSSでいじるようにしましょう。

以下は、このページのサンプルであてているCSSのコードです。

/* アコーディオン */
.container {
  margin: 0 auto;
}
.accordion {
    margin: 0;
}
button {
  border: medium none;
}

.accordion-group {
  border-left: 1px solid #ddd;
  border-right: 1px solid #ddd;
  border-top: 1px solid #ddd;
}

.accordion-header {
  background-color: #fff;
  border-bottom: 1px solid #ddd;
  border-radius: 0;
  color: #444;
  cursor: pointer;
  display: block;
  font-weight: 600;
  line-height: 1.25;
  margin: 0;
  padding: 14px 16px;
  text-align: left;
  text-decoration: none;
  transition: all 0.2s ease 0s;
  vertical-align: middle;
  white-space: normal;
  width: 100%;
  position: relative;
}
.accordion-header.active,
.accordion-header:hover,
.accordion-header:focus {
  background-color: #f1f1f1;
  color: #444;
  text-decoration: none;
}

.accordion-header:after {
  content: '\25be';
  font-size: 20px;
  color: #777;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  right: 15px;
  transition: all 0.2s ease 0s;
}
.accordion-header.active:after {
    transform: translateY(-50%) scale(1,-1);
}
/* with color */
.accordion-header.blue.active:after {
  color: #fff;
}

.accordion-panel {
  background-color: #fff;
  display: none;
  padding: 15px 20px;
  overflow: hidden;
}
.accordion-panel.show {
  border-bottom: 1px solid #ddd;
  display: block;
}
.accordion .acc-panel p:last-child {
  margin: 0;
}