アコーディオンテキストの作り方（jQuery利用）

# アコーディオンテキストの作り方

お世話になっております。コウヤです。
今回はアコーディオンテキストについて作成方法を確認していきたいと思います。

アコーディオンテキストとは以下のようなものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/2b493b7e-6ecd-d56a-2c1b-2e8893b29dfd.png)

上記の質問箇所をクリックすると、以下のように回答が出てくるものです。これの効能として、縦にページが長くならないように、必要なときのみ表示させるといったことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/92131cb0-3421-c9ae-1e68-bd7c9cc02eb6.png)

## アコーディオンテキストのHTML/CSS部分を記載する

今回のフォルダ構成は以下のとおりです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/ef8abd3f-56b1-3056-4b9c-ff290248f519.png)

なお、jQueryは予めダウンロードしてあるという前提で説明します。ダウンロードがまだの場合は以下の記事内にダウンロード方法を記載しましたので参照ください。（記事内の説明のjQueryバージョンは異なります）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/87af8e41-519a-f212-8e8b-229de82d61e2.png)



https://qiita.com/ko0821/items/8d7c063f7473eff59a9b#%E6%9B%B8%E3%81%8D%E6%96%B9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

そうしましたら、以下のHTMLコードとCSSコードを入力してください。（ここについては詳細は説明はいたしません）

```html:index.html
   <main id="FAQ" class="_bgc">
      <img src="img/03_tea1.png" class="FAQ__img">
      <h1 class="FAQ__title">FAQ</h1>   
      <div class="FAQ">
        <ul id="FAQ__list">
          <li class="FAQ__list_item">
            <h3 class="question">
              <p><span>Q</span>インターネットでの注文はできますか？</p>
              <p><img src="img/Group_cl.png" class="arrow"></p>
            </h3>
            
            <div class="answer">
              <p>注文できます。その場合配送料として別途150円かかります。</p>
            </div>
          </li>
          <li class="FAQ__list_item">
            <h3 class="question">
              <p><span>Q</span>どのような支払い方法がありますか？</p>
              <p><img src="img/Group_cl.png" class="arrow"></p>
            </h3>
            <div class="answer">
              <p>商品代引きとクレジットカード決済があります。代引き手数料は、10,800円未満で税込330円・10,800円以上32,400円未満で税込440円・32,400円以上102,400円未満で税込660円です。手数料はお客様のご負担となりますのでご了承ください。クレジットカード決済は、JCB・VISA・master・ダイナース・アメリカンエキスプレスのマークが入っているカードすべてご利用になれます。</p>
            </div>
          </li>
          <li class="FAQ__list_item">
            <h3 class="question">
              <p><span>Q</span>プレゼント用にラッピングすることはできますか？</p>
              <p><img src="img/Group_cl.png" class="arrow"></p>
            </h3>
            <div class="answer">
              <p>可能です。ラッピングが必要な場合は、購入時にフォームの「ラッピングを希望」にチェックを入れてください。</p>
            </div>
          </li>
          
        </ul>
      </div>

    </main>
```



```css:style.css
@charset "UTF-8";
/*ベース
*********************/
body {
  color: #357a38;
  font-family: "Noto Sans JP", sans-serif;
}

a {
  text-decoration: none;
  color: #357a38;
}

img {
  height: auto;
  max-width: 100%;
}

._bgc {
  height: auto;
  background: #dbebc4;
}


/*MAIN(FAQ)
**********************/
#FAQ {
  padding-top: 91px;
  padding-bottom: 91px;
  position: relative;
}

.FAQ__img {
  position: absolute;
  top: 0;
  right: 0;
  transform: translate(0, -50%);
  width: 180px;
  height: auto;
}

.FAQ__title {
  display: block;
  text-align: center;
  font-size: 32px;
  font-weight: 700;
  line-height: normal;
  margin-bottom: 90px;
}

.FAQ__list {
  margin: 0 auto;
}

.FAQ__list_item {
  margin-bottom: 31px;
}

.FAQ__list_item .question {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin: 0 auto;
  max-width: 740px;
  height: 50px;
  width: 90%;
  background-color: #fff;
  flex-shrink: 0;
  color: #357a38;
  padding-top: 12px;
  padding-bottom: 12px;
  font-size: 16px;
  font-weight: 700;
  padding-left: 14px;
  padding-right: 14px;
}

.FAQ__list_item .question:hover {
  cursor: pointer;
}

.question p:first-child {
  width: 90%;
}

.question p .arrow {
  width: 16px;
  height: 10px;
}

.question span {
  color: #357a38;
  text-align: center;
  font-size: 20px;
  font-family: Roboto;
  font-style: normal;
  font-weight: 700;
  line-height: normal;
  margin-right: 8px;
}

.question p {
  font-weight: 700;
}

.FAQ__list_item .answer {
  margin: 0 auto;
  max-width: 740px;
  width: 90%;
  color: #8d6449;
  font-size: 16px;
  font-weight: 400;
  line-height: 150%;
  margin-top: 24px;
}

.answer {
  margin-top: 24px;
  display: none;
}

.Open {
  display: block;
}

@media screen and (min-width: 768px) {
  .FAQ__qlist_item .Q {
    width: 740px;
  }
  .FAQ__list_item .question {
    font-size: 18px;
  }
  .question span {
    font-size: 24px;
  }
  .FAQ__img {
    width: 235px;
  }
}
```

## jQueryを記載していく

次にjQueryのコードを書いていきます。
まず、以下のリスト（クラスではFAQ__list_item）をクリックした際の処理を記載していきます。
つまり以下の赤枠部分です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/e7528343-bfa3-c49d-abd4-2ecc830400d3.png)

```.html
<li class="FAQ__list_item">
    <h3 class="question">
      <p><span>Q</span>インターネットでの注文はできますか？</p>
      <p><img src="img/Group_cl.png" class="arrow"></p>
    </h3>
    
    <div class="answer">
      <p>注文できます。その場合配送料として別途150円かかります。</p>
    </div>
</li>
```

この「 **FAQ__list_item** をクリックしたら」という処理は以下のように記載します。

```javascript:script_jQ.js
/*jQueryエリア*/
$(function(){
//アコーディオンメニューFAQ
	$('.FAQ__list_item').click(function(){
        //※ここにクリックした際の処理を書く
	});
});

```

上記のコードにも記載がありますが、クリックした際の処理は
```
	$('.FAQ__list_item').click(function(){

	});
```

の中に記載していきます。

### 変数の宣言
**$('.FAQ__list_item')** はこのあとも多く利用するため、ここで変数宣言をします。

```javascript:script_jQ.js
/*jQueryエリア*/
$(function(){
//アコーディオンメニューFAQ
	$('.FAQ__list_item').click(function(){
		let $answer = $(this).find('.answer');
	});
});

```
**$(this)** はthis自体が **.FAQ__list_item** を指しております。
 **.FAQ__list_item** の中にthisを指定すれば **$(this)** は **$('.FAQ__list_item')** と同じです。

次に、 **$(this).find('.answer')** ですが、 **.FAQ__list_item**の内側の **.answer**というクラスを指すようになります。

確かに以下のHTMLを見ると、 **.answer** が **$('.FAQ__list_item')** の内側にあるのが確認できます。

```.html
<li class="FAQ__list_item">
    <h3 class="question">
      <p><span>Q</span>インターネットでの注文はできますか？</p>
      <p><img src="img/Group_cl.png" class="arrow"></p>
    </h3>
    
    <div class="answer">
      <p>注文できます。その場合配送料として別途150円かかります。</p>
    </div>
</li>
```

**$(this)** はthis自体が **.FAQ__list_item** を指しているので、その状態を **$answer** という変数に入れています。

### クリックしたときのアクション
**FAQ__list_item** をクリックする際には2種類あります。空いているときと閉じているときです。

【空いているとき（Open）】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/9a265848-e438-b966-b132-00287abfd90d.png)

【閉じているとき（Close/デフォルト）】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/bd2429c2-1543-1c4b-c5aa-720893b04c8f.png)

この中で、まずは【閉じているとき】について見ていきます。

閉じているときというのは上記のHTMLコードを見ていただくと分かりますが、 **answer** にはCSSとして以下のコードが指定されています。
つまりデフォルトではdisplay:noneとなっており、表示はされていません。
```.css
.answer {
  margin-top: 24px;
  display: none;
}
```

また、 **.Open** クラスは以下のとおりです。
```.css
  .Open {
    display: block;
  }
```
これに **.Open** クラスを追加すると、.answerの中身が表示されるようになります。

つまり、以下のコードのように、 **.answer** クラスに **.Open** クラスがあるかどうかを判定する必要があります。 **hasClassメソッドでOpenクラスがあるかどうかを判定します。**

```javascript:script_jQ.js
if($answer.hasClass('Open')){
    //Openであった場合の処理
}else{
    //Openでなかった場合の処理
}
```

この中で、まず、「Openでなかった場合（閉じているデフォルトの状態）の処理」を見ていきます。
```javascript:script_jQ.js
if($answer.hasClass('Open')){
    //Openであった場合の処理
}else{
    $answer.slideDown('Open');
    $answer.addClass('Open');
    $(this).find('img').attr('src','img/Group_op.svg')
}
```

**.slideDown('Open')** メソッドで開き、ついでにOpenクラスも.answerクラスに付与します。
同時に、画像の矢印の向きも変更するようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/33e3361f-06ab-1472-9aa6-50809e5dfe8a.png)

逆に、開いているOpenであった場合のときには **.Open** クラスを削除する必要があるので、以下のように処理を記載します。

```javascript:script_jQ.js
if($answer.hasClass('Open')){
    $answer.slideUp('Open');
    $answer.removeClass('Open');
    $(this).find('img').attr('src','img/Group_cl.png');
}else{
    $answer.slideDown('Open');
    $answer.addClass('Open');
    $(this).find('img').attr('src','img/Group_op.svg')
}
```

クラスを削除するには **removeClass**メソッドを利用します。

最後に記載したjQueryコードをHTMLに反映させます。
```
    <script src="js/script_jQ.js"></script>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/bb1ebc60-4df2-2491-3d09-34dde6cd03b1.png)

これでアコーディオンテキストが動作するようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/4d279a44-2113-a46b-e187-4571ed73459a.png)


##コードまとめ

```.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="robots" content="noindex">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/style.css">
    <script src="js/jquery-2.1.4.min.js"></script> 
    <script src="js/script_jQ.js"></script>
    <title>アコーディオンテキスト</title>
</head>
<body>


  
<!--FAQ-->
    <main id="FAQ" class="_bgc">
      <img src="img/03_tea1.png" class="FAQ__img">
      <h1 class="FAQ__title">FAQ</h1>   
      <div class="FAQ">
        <ul id="FAQ__list">
          <li class="FAQ__list_item">
            <h3 class="question">
              <p><span>Q</span>インターネットでの注文はできますか？</p>
              <p><img src="img/Group_cl.png" class="arrow"></p>
            </h3>
            
            <div class="answer">
              <p>注文できます。その場合配送料として別途150円かかります。</p>
            </div>
          </li>
          <li class="FAQ__list_item">
            <h3 class="question">
              <p><span>Q</span>どのような支払い方法がありますか？</p>
              <p><img src="img/Group_cl.png" class="arrow"></p>
            </h3>
            <div class="answer">
              <p>商品代引きとクレジットカード決済があります。代引き手数料は、10,800円未満で税込330円・10,800円以上32,400円未満で税込440円・32,400円以上102,400円未満で税込660円です。手数料はお客様のご負担となりますのでご了承ください。クレジットカード決済は、JCB・VISA・master・ダイナース・アメリカンエキスプレスのマークが入っているカードすべてご利用になれます。</p>
            </div>
          </li>
          <li class="FAQ__list_item">
            <h3 class="question">
              <p><span>Q</span>プレゼント用にラッピングすることはできますか？</p>
              <p><img src="img/Group_cl.png" class="arrow"></p>
            </h3>
            <div class="answer">
              <p>可能です。ラッピングが必要な場合は、購入時にフォームの「ラッピングを希望」にチェックを入れてください。</p>
            </div>
          </li>
          
        </ul>
      </div>

    </main>


  </body>
</html>
```

```.css
@charset "UTF-8";
/*ベース
*********************/
body {
  color: #357a38;
  font-family: "Noto Sans JP", sans-serif;
}

a {
  text-decoration: none;
  color: #357a38;
}

img {
  height: auto;
  max-width: 100%;
}

._bgc {
  height: auto;
  background: #dbebc4;
}


/*MAIN(FAQ)
**********************/
#FAQ {
  padding-top: 91px;
  padding-bottom: 91px;
  position: relative;
}

.FAQ__img {
  position: absolute;
  top: 0;
  right: 0;
  transform: translate(0, -50%);
  width: 180px;
  height: auto;
}

.FAQ__title {
  display: block;
  text-align: center;
  font-size: 32px;
  font-weight: 700;
  line-height: normal;
  margin-bottom: 90px;
}

.FAQ__list {
  margin: 0 auto;
}

.FAQ__list_item {
  margin-bottom: 31px;
}

.FAQ__list_item .question {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin: 0 auto;
  max-width: 740px;
  height: 50px;
  width: 90%;
  background-color: #fff;
  flex-shrink: 0;
  color: #357a38;
  padding-top: 12px;
  padding-bottom: 12px;
  font-size: 16px;
  font-weight: 700;
  padding-left: 14px;
  padding-right: 14px;
}

.FAQ__list_item .question:hover {
  cursor: pointer;
}

.question p:first-child {
  width: 90%;
}

.question p .arrow {
  width: 16px;
  height: 10px;
}

.question span {
  color: #357a38;
  text-align: center;
  font-size: 20px;
  font-family: Roboto;
  font-style: normal;
  font-weight: 700;
  line-height: normal;
  margin-right: 8px;
}

.question p {
  font-weight: 700;
}

.FAQ__list_item .answer {
  margin: 0 auto;
  max-width: 740px;
  width: 90%;
  color: #8d6449;
  font-size: 16px;
  font-weight: 400;
  line-height: 150%;
  margin-top: 24px;
}

.answer {
  margin-top: 24px;
  display: none;
}

  .Open {
    display: block;
  }

@media screen and (min-width: 768px) {
  .FAQ__qlist_item .Q {
    width: 740px;
  }
  .FAQ__list_item .question {
    font-size: 18px;
  }
  .question span {
    font-size: 24px;
  }
  .FAQ__img {
    width: 235px;
  }
}
```


```.js

/*jQueryエリア*/
$(function(){

//アコーディオンメニューFAQ
	$('.FAQ__list_item').click(function(){
		let $answer = $(this).find('.answer');

		if($answer.hasClass('Open')){
			$answer.slideUp('Open');
			$answer.removeClass('Open');
			$(this).find('img').attr('src','img/Group_cl.png');
		}else{
			$answer.slideDown('Open');
			$answer.addClass('Open');
			$(this).find('img').attr('src','img/Group_op.svg')
		}
	});

});

```