jQueryで作るアコーディオンメニュー

商用サイトのQ&Aなどによく使われるアコーディオンメニュー。

アコーディオンメニュー

質問部分をクリックすると回答部分が表示されるので、ユーザーが必要とする情報だけ表示できるので画面もスッキリします。

アコーディオンメニューの作り方はいろいろありますが、一番簡単な作り方は「jQUERY」を利用したアコーディオンメニューではないでしょうか。

何しろjQUERYの「next」と「slideDowm」というメソッドを使うだけで、いとも簡単に基本的なアコーディオンメニューが作れてしまいます。

今日は「jQuery」を使ってアコーディオンメニューを作りたいと思います。

基本的なアコーディオンメニュー

質問部分をクリックすると回答部分が開く、最も基本的なアコーディオンメニューを作りたいと思います。

See the Pen accordion-jquery1 by konpure (@yuntu) on CodePen.

質問部分をクリックしていただくと回答部分が表示されます。

再度質問部分をクリックすると回答部分が閉じます。

HTML

<div class="accordion">
  <dl class="accordion-box">
    <dt class="question">Question1</dt><!-- /.question -->
    <dd class="answer">Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
    <dl class="accordion-box">
    <dt class="question">Question2</dt><!-- /.question -->
    <dd class="answer">Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
    <dl class="accordion-box">
    <dt class="question">Question3</dt><!-- /.question -->
    <dd class="answer">Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
  <dl class="accordion-box">
    <dt class="question">Question4</dt><!-- /.question -->
    <dd class="answer">Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
</div>

<!-- jQueryの読み込み -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

jQueryを使うのでbody閉じタグの手前でjQueryを読み込ませることを忘れないことが重要です。

それ以外は特に気を付ける部分はありません。

CSS

*,
*::after,
*::before {
  box-sizing: border-box;
}
  
body {
  background: #e6dbc7;
}
  
dl,
dt,
dd {
  margin: 0;
  padding: 0;
}

/*------------------------------

ここからアコーディオンのCSS

------------------------------*/

/* アコーディオンメニューの大きさ */
.accordion {
  width: 500px;
  max-width: 100%;
}

/* アコーディオンメニューの間隔 */
.accordion-box:not(:first-child) {
  margin-top: 20px;
}
  
/* 質問部分 */
.question {
  background: #52a261;
  padding: 20px 20px 20px 80px;
  font-size: 18px;
  color: #fff;
  font-weight: 700;
  position: relative;
}
  
/* Qマーク */
.question::before {
  content: 'Q';
  font-size: 40px;
  color: #1d1d74;
  position: absolute;
  left: 20px;
  top: 50%;
  transform: translateY(-50%);
}
  
/* 回答部分は最初非表示 */
.answer {
  display: none;/* 非表示にしておく */
  padding: 20px 20px 20px 80px;
  font-size: 18px;
  background: #fff;
  position: relative;
}

/* Aマーク */
.answer::before {
  content: 'A';
  font-size: 40px;
  font-weight: 700;
  color: #1d1d74;
  position: absolute;
  left: 20px;
  top: 50%;
  transform: translateY(-50%);
}

重要なのは初期状態で回答部分をdisplay:noneで非表示にしておくことくらいで、特に難しいこともありません。

質問部分と回答部分には疑似要素により「Q」というマークと「A」というマークを付けています。

「Q」と「A」のマークはpositionを使って適当な場所に置いています。

jQuery

$(function() {
  $('.question').click(function() {
    $(this).next().slideToggle(400);
  });
});

質問部分がクリックされたらイベントが発火します。

$(this).next()によりクリックされた質問部分の次の要素(回答部分)が指定されます。

そしてそれをslideToggleメソッドに繋げます。

slideToggleメソッドは要素の表示と非表示をスライドさせながら切り替えることができるメソッドです。

slideToggleの()の中の数字は表示や非表示の速度設定(ミリ秒)です。

つまり$(this).next().slideToggle(400)により、クリックされた質問部分の隣の要素である回答部分が閉じていれば回答部分が0.4秒の時間をかけてスライド式に開かれ、開いていれば逆に0.4秒の時間をかけてスライド式に閉じられます

たったこれだけで基礎的なアコーディオンメニューが完成します。

ゆんつ
簡単!

クリックされた質問部分以外の回答は閉じる

先ほどのアコーディオンメニューは、質問部分をクリックし回答部分が開いたままの状態で他の質問部分をクリックした場合そのまま他の質問部分の回答も開きます。

これでも別に構わないとは思いますが、質問部分を複数クリックすると回答部分もそれだけ開いてしまうので場所をとります。

ゆんつ
直近でクリックした質問以外は自動的に閉じてくれたほうが画面がスッキリするなあ

ということもあるかもしれません。

そこでクリックした質問に対する回答部分だけが表示され、他の回答が開いている場合は自動的に閉じるようにしたいと思います。

See the Pen accordion-jquery2 by konpure (@yuntu) on CodePen.

HTML

<div class="accordion">
  <dl class="accordion-box">
    <dt class="question">Question1</dt><!-- /.question -->
    <dd class="answer">Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
    <dl class="accordion-box">
    <dt class="question">Question2</dt><!-- /.question -->
    <dd class="answer">Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
    <dl class="accordion-box">
    <dt class="question">Question3</dt><!-- /.question -->
    <dd class="answer">Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
  <dl class="accordion-box">
    <dt class="question">Question4</dt><!-- /.question -->
    <dd class="answer">Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
</div>

<!-- jQueryの読み込み -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

先ほどの基本的なアコーディオンメニューのものと同じです。

CSS

*,
*::after,
*::before {
  box-sizing: border-box;
}
  
body {
  background: #e6dbc7;
}
  
dl,
dt,
dd {
  margin: 0;
  padding: 0;
}

/*------------------------------

ここからアコーディオンのCSS

------------------------------*/

/* アコーディオンメニューの大きさ */
.accordion {
  width: 500px;
  max-width: 100%;
}

/* アコーディオンメニューの間隔 */
.accordion-box:not(:first-child) {
  margin-top: 20px;
}
  
/* 質問部分 */
.question {
  background: #52a261;
  padding: 20px 20px 20px 80px;
  font-size: 18px;
  color: #fff;
  font-weight: 700;
  position: relative;
}
  
/* Qマーク */
.question::before {
  content: 'Q';
  font-size: 40px;
  color: #1d1d74;
  position: absolute;
  left: 20px;
  top: 50%;
  transform: translateY(-50%);
}
  
/* 回答部分は最初非表示 */
.answer {
  display: none;/* 非表示にしておく */
  padding: 20px 20px 20px 80px;
  font-size: 18px;
  background: #fff;
  position: relative;
}

/* Aマーク */
.answer::before {
  content: 'A';
  font-size: 40px;
  font-weight: 700;
  color: #1d1d74;
  position: absolute;
  left: 20px;
  top: 50%;
  transform: translateY(-50%);
}

先ほどの基本的なアコーディオンメニューのものと同じです。

jQuery

$(function() {
  $('.question').click(function() {
    //クリックされた質問部分に対する回答以外は全て閉じる
    $('.question').not(this).next().slideUp(400);
    
    //クリックされた質問に対する回答を表示する
    $(this).next().slideToggle(300);
  });
});

先ほどの基本的なアコーディオンメニューとの違いは、まず最初にクリックされた質問に対する回答以外をslideUpメソッドで閉じていることです。

これにより別の質問部分をクリックした場合に、それまで開いていた回答部分が閉じられることになります。

そのうえでslideToggleでクリックされた質問に対する回答部分を表示するようにしています。

以上で、直近でクリックした質問に対する回答以外を自動的に閉じるアコーディオンメニューが完成します。

開いている状態と閉じている状態をアイコンで表示する

アコーディオンが閉じている時は「+」開いている時は「-」のアイコンを質問部分の右端につけて開閉の状態がアイコンでわかるようにします。

See the Pen accordion-jquery3 by konpure (@yuntu) on CodePen.

質問部分をクリックしていただけるとプラスマークがマイナスマークに変化し回答が表示されます。

再度同じ質問部分をクリックするか、他の質問をクリックするとプラスマークに戻ります。

HTML

<div class="accordion">
  <dl class="accordion-box">
    <dt class="question"><span></span>Question1</dt><!-- /.question -->
    <dd class="answer">Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
    <dl class="accordion-box">
    <dt class="question"><span></span>Question2</dt><!-- /.question -->
    <dd class="answer">Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
    <dl class="accordion-box">
    <dt class="question"><span></span>Question3</dt><!-- /.question -->
    <dd class="answer">Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
  <dl class="accordion-box">
    <dt class="question"><span></span>Question4</dt><!-- /.question -->
    <dd class="answer">Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4</dd><!-- /.answer -->
  </dl><!-- /.accordion-box -->
</div>

<!-- jQueryの読み込み -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

これまでのHTMLとの違いは、「プラスマーク」のアイコンをつけるために質問部分に空のspan要素を入れていることです。

このspanにCSSで疑似要素を設定してプラスマークを作成します。

CSS

*,
*::after,
*::before {
  box-sizing: border-box;
}
  
body {
  background: #e6dbc7;
}
  
dl,
dt,
dd {
  margin: 0;
  padding: 0;
}

/*------------------------------

ここからアコーディオンのCSS

------------------------------*/

/* アコーディオンメニューの大きさ */
.accordion {
  width: 500px;
  max-width: 100%;
}

/* アコーディオンメニューの間隔 */
.accordion-box:not(:first-child) {
  margin-top: 20px;
}
  
/* 質問部分 */
.question {
  background: #52a261;
  padding: 20px 20px 20px 80px;
  font-size: 18px;
  color: #fff;
  font-weight: 700;
  position: relative;
}
  
/* Qマーク */
.question::before {
  content: 'Q';
  font-size: 40px;
  color: #1d1d74;
  position: absolute;
  left: 20px;
  top: 50%;
  transform: translateY(-50%);
}
  
/* プラスマークアイコン */
.question span::before,
.question span::after {
  content: '';
  display: block;
  width: 30px;
  height: 3px;
  background: #fff;
  border-radius: 10px;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  transition: .5s;
}

/* プラスマークアイコンの横棒の位置調整など*/
.question span::before {
  right: 30px;
}
  
/* プラスマークアイコンの縦棒の位置調整など*/
.question span::after {
  right: 30px;
  transform: translateY(-50%) rotate(90deg);
}

/* 回答部分が開いている時は縦棒を横にする*/
.question span.open::after {
  transform: translateY(-50%) rotate(0);
}

/* 回答部分は最初非表示 */
.answer {
  display: none;/* 非表示にしておく */
  padding: 20px 20px 20px 80px;
  font-size: 18px;
  background: #fff;
  position: relative;
}

/* Aマーク */
.answer::before {
  content: 'A';
  font-size: 40px;
  font-weight: 700;
  color: #1d1d74;
  position: absolute;
  left: 20px;
  top: 50%;
  transform: translateY(-50%);
}

これまでのCSSとの違いはプラスマークのアイコンを作成するためにspan要素に疑似要素を設定していることと、回答部分が開いている時に「マイナスマーク」に変化させるため「open」という縦棒を横棒に変化させるスタイルを持ったクラスを設定していることです。

このopenというクラスをjQueryを使ってspan要素に付け外しすることで、アイコンを「プラスマーク」から「マイナスマーク」へと変化させます。

jQuery

$(function() {
  $('.question').click(function() {
    //クリックされた質問の子要素のspan以外からはopenというクラスを外す
    $('.question').not(this).children('span').removeClass('open');
    //クリックされた質問部分に対する回答以外は全て閉じる
    $('.question').not(this).next().slideUp(400);
    
    //クリックされた質問の子要素のspanにopenクラスが付与されいなければ付与し、付与されていれば外す
    $(this).children('span').toggleClass('open');
    //クリックされた質問に対する回答を表示する
    $(this).next().slideToggle(400);
  });
});

まずクリックされた質問以外のspanからはopenクラスを外します。

これによりクリックされた質問部分のspanにだけopenクラスがついてアイコンを変化させることができます。

そして改めてクリックされた質問部分のspanについて、openクラスが付与されていなければ付与して縦棒を横にして「マイナスマーク」に変化させ、openクラスが付与されていれば外して「マイナスマーク」を「プラスマーク」に変化させます。

質問部分の表示非表示に関しては先ほどの「クリックされた質問部分以外の回答は閉じる」と同じです。

以上で、質問がクリックされたらアイコンが変化し回答が表示されるアコーディオンメニューが完成します。

まとめ

以上のようにアコーディオンメニューは

「jQuery」の「nextメソッド」と「slidedownメソッド」

を使うことでとても簡単に作れます。

そして状況に応じて開閉状態を示すアイコンをつけたり、jQueryを少し追加してクリックされた質問に対する回答以外は閉じるようにしたりすると、より使いやすいアコーディオンメニューになると思います

何かの参考になれば幸いです。

ちなみにアコーディオンメニューは「CSSだけ」でも作ることができます。

その方法は以下の記事に書いておりますので、興味があればご覧ください。

ゆんつ
それでは、またー