アコーディオン(Accordion)を自作する方法

今回は、アコーディオン(Accordion)を自作してみます。

自作するにあたり以下のサイトを参考にしています。

シンプル版(アニメ効果なし)

まず、最初に一番シンプルなアコーディンを紹介します。

サンプル

セクション1の内容…

セクション2の内容…

セクション3の内容…

HTMLコード

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
  <title> Collapsibles/Accordion demo(1)</title>
  <style type="text/css">
    /* Style the buttons that are used to open and close the accordion panel */
    .accordion {
      background-color: #eee;
      color: #444;
      cursor: pointer;
      padding: 18px;
      width: 100%;
      text-align: left;
      border: none;
      outline: none;
      transition: 0.4s;
    }
    /* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
    .active, .accordion:hover {
      background-color: #ccc;
    }
    /* Style the accordion panel. Note: hidden by default */
    .panel {
      padding: 0 18px;
      background-color: white;
      display: none;
      overflow: hidden;
    }
  </style>
</head>
<body>
  <button class="accordion">セクション 1</button>
  <div class="panel">
    <p>セクション1の内容...</p>
  </div>
  <button class="accordion">セクション 2</button>
  <div class="panel">
    <p>セクション2の内容...</p>
  </div>
  <button class="accordion">セクション 3</button>
  <div class="panel">
    <p>セクション3の内容...</p>
  </div>
  <script type="text/javascript">
    var acc = document.getElementsByClassName("accordion");
    var i;
    for (i = 0; i < acc.length; i++) {
      acc[i].addEventListener("click", function() {
        /* Toggle between adding and removing the "active" class,
        to highlight the button that controls the panel */
        this.classList.toggle("active");
        /* Toggle between hiding and showing the active panel */
        var panel = this.nextElementSibling;
        if (panel.style.display === "block") {
          panel.style.display = "none";
        } else {
          panel.style.display = "block";
        }
      });
    }
  </script>
</body>
</html>

デモ

実装方法

スタイルシート定義

まず、スタイルシートを定義します。

<style type="text/css">
  /* Style the buttons that are used to open and close the accordion panel */
  .accordion {
    background-color: #eee;
    color: #444;
    cursor: pointer;
    padding: 18px;
    width: 100%;
    text-align: left;
    border: none;
    outline: none;
    transition: 0.4s;
  }
  /* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
  .active, .accordion:hover {
    background-color: #ccc;
  }
  /* Style the accordion panel. Note: hidden by default */
  .panel {
    padding: 0 18px;
    background-color: white;
    display: none;
    overflow: hidden;
  }
</style>

HTMLマークアップ

まず、ボタン(<button>)でアコーディオンのパネルを開くための領域を設定します。

<button class="accordion">セクション 1</button>

classに『accordion』を設定します。

次に、アコーディオンの内容領域を設定します。

<button class="accordion">セクション 1</button>
<div class="panel">
  <p>セクション1の内容...</p>
</div>

ボタン(<button>)のclass『accordion』要素の次にアコーディオンの内容領域を設定します。DIVで、class『panel』を指定してください。

Javascriptコード追加

<script type="text/javascript">
  var acc = document.getElementsByClassName("accordion");
  var i;
  for (i = 0; i < acc.length; i++) {
    acc[i].addEventListener("click", function() {
      /* Toggle between adding and removing the "active" class,
      to highlight the button that controls the panel */
      this.classList.toggle("active");
      /* Toggle between hiding and showing the active panel */
      var panel = this.nextElementSibling;
      if (panel.style.display === "block") {
        panel.style.display = "none";
      } else {
        panel.style.display = "block";
      }
    });
  }
</script>

最後に、Javascriptコードを定義します。class『accordion』が設定されているオブジェクトに対して、クリックイベントを仕掛けていきます。

accordion』がクリックされると、クリックされたオブジェクトに対して、class『active』が設定、または、解除され、かつ、次のオブジェクトである『panel』を表示/非表示させます。

効果(アニメーション)ありアコーディオン

次に、少しだけ、効果(アニメーション)を付けてみます。

サンプル

セクション1の内容...

セクション2の内容...

セクション3の内容...

デモ

実装方法

スタイルシート定義

<style type="text/css">
  /* Style the buttons that are used to open and close the accordion panel */
  .accordion {
    background-color: #eee;
    color: #444;
    cursor: pointer;
    padding: 18px;
    width: 100%;
    text-align: left;
    border: none;
    outline: none;
    transition: 0.4s;
  }
  /* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
  .active, .accordion:hover {
    background-color: #ccc;
  }
  /* Style the accordion panel. Note: hidden by default */
  .panel {
    padding: 0 18px;
    background-color: white;
    overflow: hidden;
    max-height: 0;
    transition: max-height 0.2s ease-out;
  }
</style>

アコーディオンの内容領域のclass『panel』の定義を少し修正すると、アコーディオンを開くとき、または、閉じるときに、次第に開く、または、閉じるような効果を入れることができます。

アイコン付アコーディオン(サイト参考版)

アコーディオンがあることをわかりやすく、また、閉じている/開いている状態をわかりやすくするためにプラス/マイナスのアイコンを付けてみます。

サンプル

セクション1の内容...

セクション2の内容...

セクション3の内容...

デモ

実装方法

スタイルシート定義

<style type="text/css">
  /* Style the buttons that are used to open and close the accordion panel */
  .accordion {
    background-color: #eee;
    color: #444;
    cursor: pointer;
    padding: 18px;
    width: 100%;
    text-align: left;
    border: none;
    outline: none;
    transition: 0.4s;
  }
  .accordion:after {
    content: '\02795'; /* Unicode character for "plus" sign (+) */
    font-size: 13px;
    color: #777;
    float: right;
    margin-left: 5px;
  }
  .active:after {
    content: "\2796"; /* Unicode character for "minus" sign (-) */
  }
  /* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
  .active, .accordion:hover {
    background-color: #ccc;
  }
  /* Style the accordion panel. Note: hidden by default */
  .panel {
    padding: 0 18px;
    background-color: white;
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.2s ease-out;
  }
</style>

クラス『accordion』の疑似クラス(:after)に、アイコン(プラス)と、選択済みのクラス『active』の議事クラス(:after)に、アイコン(マイナス)を定義します。

これで、アコーディオン領域の右側に、プラスとマイナスのアイコンを設定することができます。

左アイコン付アコーディオン

アイコンは右側にあるより、左側にあるほうがわかりやすいので、左側に設定するようにカスタマイズしてみます。

サンプル

セクション1の内容...

セクション2の内容...

セクション3の内容...

デモ

実装方法

スタイルシート定義

<style type="text/css">
  /* Style the buttons that are used to open and close the accordion panel */
  .accordion {
    background-color: #eee;
    color: #444;
    cursor: pointer;
    padding: 18px;
    width: 100%;
    text-align: left;
    border: none;
    outline: none;
    transition: 0.4s;
  }
  .accordion:after {
    content: '\02795'; /* Unicode character for "plus" sign (+) */
    font-size: 13px;
    color: #777;
    float: left;
    margin-right: 5px;
  }
  .active:after {
    content: "\2796"; /* Unicode character for "minus" sign (-) */
  }
  /* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
  .active, .accordion:hover {
    background-color: #ccc;
  }
  /* Style the accordion panel. Note: hidden by default */
  .panel {
    padding: 0 18px;
    background-color: white;
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.2s ease-out;
  }
</style>

クラス『accordion』の疑似クラス(:after)の定義を少し、修正するだけで、アイコンは左側に移動します。「float」を『left』に変更し、「margin-left」を「margin-right」に変更するだけです。

開くアコーディオンを一つだけにする

通常、アコーディオンは開いている項目が一つだけのことが多いので、そういう風にカスタマイズしてみます。

サンプル

セクション1の内容...

セクション2の内容...

セクション3の内容...

デモ

実装方法

Javascriptコード追加

Javascriptのコードを一部修正することで、選択済み以外の領域を自動的に閉じるようにします。

<script type="text/javascript">
  var acc = document.getElementsByClassName("accordion");
  var i;
  var currentAccordion = document.querySelector(".active");
  if ( currentAccordion != undefined ) {
    var currentPanel = currentAccordion.nextElementSibling;
    currentPanel.style.maxHeight = currentPanel.scrollHeight + "px";
  }
  for (i = 0; i < acc.length; i++) {
    acc[i].addEventListener("click", function() {
      /* 開いているアコーディオンを閉じる */
      var activeAccordion = document.querySelector(".active");
      if( activeAccordion != undefined )  {
        activeAccordion.classList.toggle("active");
        var activePanel= activeAccordion.nextElementSibling;
        if (activePanel.style.maxHeight) {
          activePanel.style.maxHeight = null;
        } else {
          activePanel.style.maxHeight = panel.scrollHeight + "px";
        }
      }
      /* 閉じているアコーディオンを開く */
      this.classList.toggle("active");
      var panel = this.nextElementSibling;
      if (panel.style.maxHeight) {
        panel.style.maxHeight = null;
      } else {
        panel.style.maxHeight = panel.scrollHeight + "px";
      }
    });
  }
</script>

クリックした領域を開く前に、現在、class『active』が設定されている領域から『active』を削除し、その領域を閉じるようにしてあります。

また、初期表示時、class『active』を設定することで、初期表示時、開いた状態で表示させることができます。

ご参考

関連ページ