高さが可変のアニメーションするアコーディオンメニュー　【JavaScript】【高さ可変】【脱jQuery】

アコーディオンメニューはサイトの様々な箇所で使われるため、ページの中で複数箇所に設置でき、CSSで容易に装飾を変更できるものを作りました。
特に、アコーディオンのコンテンツの高さをcssで都度指定の必要がないことも使い回しのポイントです。

# 動作デモ

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="js,result" data-user="marchin133" data-slug-hash="KKpMrmJ" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="アコーディオンメニュー">
  <span>See the Pen <a href="https://codepen.io/marchin133/pen/KKpMrmJ">
  アコーディオンメニュー</a> by masato yamada (<a href="https://codepen.io/marchin133">@marchin133</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


#使い方

JavaScriptを読み込み、cssに追記します。

##JavaScript
別ファイルなどにして読み込んでください

```javascript:acordion.js
document.addEventListener('DOMContentLoaded', function () {

    var acodionMenu = document.querySelectorAll('.acdn');
    var acodionContentHight = [];

    for (var i = 0; i < acodionMenu.length; i++) {

        acodionContentHight[i] = acodionMenu[i].nextElementSibling.clientHeight + "px";
        acodionMenu[i].nextElementSibling.style.height = acodionContentHight[i];

            if (acodionMenu[i].nextElementSibling.classList.contains('acdn_close')) {
                acodionMenu[i].nextElementSibling.style.height = '0px';
            }

        acodionMenu[i].addEventListener('click', function () {

            var clickitem = Array.prototype.indexOf.call(acodionMenu, this);

            if (this.nextElementSibling.classList.contains('acdn_close')) {
                this.nextElementSibling.style.height = acodionContentHight[clickitem];
            } else {
                this.nextElementSibling.style.height = '0px';
            }

            this.classList.toggle('acdn_open');
            this.classList.toggle('acdn_close');
            this.nextElementSibling.classList.toggle('acdn_open');
            this.nextElementSibling.classList.toggle('acdn_close');

        }, false);

    }
    

}, false);
```

##html
１）アコーディオンの開閉に使う要素に、`.acdn` クラスをつけてください。
２）ページが表示されたときに閉じているときは`.acdn_close` も付与してください。逆に展開しているときは`.acdn_open`をつけてください。
３）`.acdn`が付けられた要素の**次**の要素がアコーディオンとして機能します。その要素に展開状態を示す`.acdn_close`または`.acdn_open`を付与してください。
４）htmlはこれだけです。

```html:sample.html
<div class="menu_title acdn acdn_close">アコーディオンメニュー１</div> <!-- 閉じた状態で表示させたい場合 -->
    <div class="menu_content acdn_close">
        <ul>
            <li>項目１</li>
            <li>項目２</li>
            <li>項目３</li>
            <li>項目４</li>
        </ul>
    </div>
    <div class="menu_title acdn acdn_open">アコーディオンメニュー2</div> <!-- 開いた状態で表示させたい場合 -->
    <div class="menu_content acdn_open">
        <ul>
            <li>項目１</li>
            <li>項目２</li>
            <li>項目３</li>
            <li>項目４</li>
        </ul>
    </div>
    <div class="menu_title acdn acdn_open">アコーディオンメニュー2</div>
    <div class="menu_content acdn_open">
        <ul>
            <li>項目１</li>
            <li>項目２</li>
            <li>項目３</li>
            <li>項目４</li>
        </ul>
    </div>
```

##CSS
１）`.menu_title` クラス名不問 アコーディオンの開閉として使用する要素です。自由に装飾してください。jsでクリックイベントが付きますので、面積があったほうがいいです。
２）`.menu_content` クラス名不問　アコーディオンで高さを、もともとの高さ→0pxになる要素です。必要に応じて装飾ください。

`overflow: hidden;`　この内側の要素を消す（見えなくする）ために必要です。
`transition: all 0.5s ease-out;`　トランジションはお好きな数値に変更などしてください。設定しないとアニメーションしません。

３）要素に`.acdn_close`または`.acdn_open`が付与されることを利用して、展開時や縮小時に表現を変えることができます。
例：サンプルでは押された要素（`.menu_title`）の背景色を変えています。

```css:sample.css
.menu_title{
  width:400px;
  height: 50px;
}

.menu_content{
  width:400px;
  overflow: hidden;
  transition: all 0.5s ease-out;
}

.menu_title.acdn_open{
  background-color: #cccccc;
}

```

##動作のしくみ

`.acdn`が付けらた要素にクリックイベントを付け、その次の要素の高さを取得しています。
一度高さを格納したあとに、`.acdn_close`がついている要素については高さを0pxに設定して閉じた状態にしています。
高さが画面描画後に動的に変更されない限り、アコーディオンコンテンツの中身の高さを調べてcssに記述することなく、トランジションさせることができます。

クリックイベントが起きるたび、要素に`.acdn_close`または`.acdn_open`を都度付けたり消したりすることで動きを実現しています。

コードが冗長であるなど、ご指摘いただけると嬉しいです。