JavaScriptとCSSでアコーディオンメニューを作る

CSS

今回はJavaScriptとCSSでアコーディオンメニューを作っていきたいと思います。

完成形はこんな感じです。

アコーディオンメニューの完成形
アコーディオンメニューの完成形

アコーディオンメニューの作成

今回のファイル構成です。全部同じディレクトリにあります。

- index.html
- style.css
- scripts.js

index.htmlファイルの作成

まず、index.htmlファイルを用意して、style.cssとscripts.jsを読み込みます。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>アコーディオンメニュー</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <nav id="menu">
      <div class="accordion">
        犬の種類
        <div class="symbol"><span></span><span></span></div>
      </div>
      <ul class="panel">
        <li><a href="#">トイプードル</a></li>
        <li><a href="#">チワワ</a></li>
        <li><a href="#">柴犬</a></li>
        <li><a href="#">ポメラニアン</a></li>
        <li><a href="#">ブルドッグ</a></li>
      </ul>
      <div class="accordion">
        猫の種類
        <div class="symbol"><span></span><span></span></div>
      </div>
      <ul class="panel">
        <li><a href="#">スコティッシュフォールド</a></li>
        <li><a href="#">マンチカン</a></li>
        <li><a href="#">アメリカンショートヘア</a></li>
        <li><a href="#">ラグドール</a></li>
        <li><a href="#">ロシアンブルー</a></li>
      </ul>
      <div class="accordion">
        鳥の種類
        <div class="symbol"><span></span><span></span></div>
      </div>
      <ul class="panel">
        <li><a href="#">セキセイインコ</a></li>
        <li><a href="#">文鳥</a></li>
        <li><a href="#">コザクラインコ</a></li>
        <li><a href="#">オカメインコ</a></li>
        <li><a href="#">ヨウム</a></li>
      </ul>
    </nav>
    <section id="main"><h1 id="title">メインコンテンツ</h1></section>
    <script src="scripts.js"></script>
  </body>
</html>

bodyタグの直下に<nav id=”menu”>と <section id=”main”>を置いて、navにはアコーディオンメニューを、sectionにはメインコンテンツを置くというレイアウトです。

後でレスポンシブ対応も行います。

アコーディオンメニュー内では、<div class=”accordion”>の部分をクリックすると<ul class=”panel”>内のメニューが展開する予定です。

<div class=”symbol”>は、アコーディオンが展開によって+とーが切り替わるようにします。

コードをまとめて出していますが、実際にはCSSやJavaScriptと同時に編集しています。

style.cssファイルの作成

index.htmlと同じディレクトリにstyle.cssを作成して、コードを書きます。

まずはレイアウトとアコーディオン部分です。

@import url("https://fonts.googleapis.com/css2?family=Zen+Maru+Gothic:wght@400;700&display=swap");
body {
  display: flex;
  margin: 0;
  font-family: "Zen Maru Gothic", sans-serif;
}
a {
  color: #dba39a;
  text-decoration: none;
}
#main {
  width: 100%;
  background-color: #fefcf3;
  color: #dba39a;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 600px;
}
#menu {
  min-width: 250px;
}
@media screen and (max-width: 600px) {
  body {
    flex-wrap: wrap;
  }
  #menu {
    width: 100%;
  }
}
.accordion {
  background-color: #f5ebe0;
  color: #dba39a;
  cursor: pointer;
  padding: 18px;
  border: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.panel {
  list-style-type: none;
  margin: 0;
  padding: 0 18px;
  background-color: #fefcf3;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease;
}
.panel li {
  margin: 10px;
}

フォントは、Google fontsのZen Maru Gothicを使っています。

bodyでdisplay: flex;にして、メニュー部分とメインコンテンツを横に並べています。

画面幅が600px以下になると、bodyの flex-wrap: wrap; で、メニュー部分とメインコンテンツの並びが縦になります。

アコーディオンのクリックできる部分(.accordion)は、cursor: pointer;にしてクリッカブルだということを明示しています。

アコーディオンの展開する部分(.panel)は、いったんmax-height: 0;と、overflow: hidden;で見えないように隠しています。後でJavaScriptで、max-heightの数値を変更します。

transitionの記述はアニメーションの設定です。

あとは、全体的に余白だったり色だったりを調整しています。

scripts.jsの作成

次はJavaScript部分の記述に入っていきます。

同じディレクトリにscripts.jsを作成してコードを書きます。

const accordions = document.getElementsByClassName("accordion");

for (let i = 0; i < accordions.length; i++) {
  accordions[i].addEventListener("click", function () {
    this.classList.toggle("active");
    const panel = this.nextElementSibling;
    if (panel.style.maxHeight) {
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
    }
  });
}

まず、.accordionから複数の要素を取り出して、accordionsに収めます。ちなみに複数なのでsをつけています。

forループを使って、取り出したaccordionsの要素ひとつずつにイベントリスナーを付与していきます。

function() {}のthisは、この場合、accordion[0]とかaccordion[1]とかに当たります。

クリックされたら.accordionのクラスリストに”active”をつけたり外したりします。
これは後の+ーマークの切り替えで使います。

変数panelは、thisのnextElementSibling、つまりclass=”accordion”の弟(or妹)要素のことを示しています。
class=”panel”のことですね。

siblingはきょうだい
siblingはきょうだい

次のif文では、panelのstyleのmax-heightが指定されていればそれをnullにして、そうでなければmax-heightを指定しています。CSSのインライン記述のstyle=”max-height: 〇〇px”のことです。

scrollHeightと言うのは、隠れている部分も含めての要素の高さのプロパティです。それに単位のpxをつけてmax-heightを指定しています。

ちなみにCSSのmax-heightはJavaScripではmaxHeightと書きます。

アコーディオン動作の確認

ではここまでの動きを見てみましょう。

アコーディオンは動作している
アコーディオンは動作している

きちんとアコーディオンメニューが動作していますね。

次はプラス・マイナスマークを作成します。

プラス・マイナスのマークの作成

すでにindex.htmlには、class=”symbol”の下にspanタグを2つ用意しているので、これに対してCSSで形や動きを作っていきます。

形を作る

style.cssに下記を追記します。

.symbol {
  width: 30px;
  height: 30px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.symbol span {
  display: block;
  background-color: #dba39a;
  width: 100%;
  height: 1px;
  transition: all 0.4s ease;
}
.symbol span:nth-of-type(1) {
  transform: translateX(15px);
}
.symbol span:nth-of-type(2) {
  transform: rotate(-90deg);
}

.symbolは縦横30pxの正方形で、中身はflex-boxを使って要素を縦横中央に揃えています。

中身のspanは1pxの細さの線です。この時点では2本ともただの横棒ですね。

nth-of-type(1)で1本めの線を指定して、右に15px移動。

nth-of-type(2)で2本目の線を指定して、-90度回転。

これでプラスマークができました。

2本の線を交差させてプラスマークができた

動きを作る

次はアコーディオンが開いたときには2本の線が重なって、マイナスになるようにしたいところです。

scripts.jsで記述したように、アコーディオンが開いているときには、.accordionのクラスリストに”active”が追加されるのでこれを利用します。

先程のCSSの下に下記コードを追記します。

.accordion.active .symbol span:nth-of-type(2) {
  transform: rotate(0deg);
}

.accordionが”active”のときに、その下の.symbolの下の、2個めのspanを指定して、回転を0度に戻しています。

これで2本の線が重なってマイナスになります。

アコーディオンが開くとマイナスになった

こんな感じでアコーディオンメニューができました。

Codepenを貼っておきます

最後にCodepenを貼っておきます。

レスポンシブでレイアウトが変わります。600pxがブレークポイントです。

See the Pen Untitled by tkyytnm (@tkyytnm) on CodePen.

以上です。ご参考になれば。

コメント

タイトルとURLをコピーしました