CSSだけで作るアコーディオンメニュー

商用のWEBサイトをみていると、よく「Q&A」を見かけます。

「Q&A」の内容は、そのサイトで紹介している商品やサービスなどに対する質問と、それに対する回答というのが多いと思います。

「Q&A」は最初から質問も回答も全て表示されている場合もありますが、質問の部分をクリックすると回答が現れるものも良く見かけます。

アコーディオンメニュー

このようにクリックやタップをすることで隠れていた要素が現れて情報が表示されるような仕組みを「アコーディオンメニュー」と言います。

サイトの利用者がクリックした質問の回答のみを表示することができるのでQ&A部分をコンパクトにすることができ、スペースを節約することができます。

このアコーディオンメニューはjQueryで作ることもできますが、HTMLとCSSだけでも作成することができます。

今回は「HTMLとCSSだけで作るアコーディオンメニュー」について書きたいと思います。

基本的な作り方

以下のようなアコーディオンメニューを作成します

See the Pen accordion1 by konpure (@yuntu) on CodePen.

Question部分をクリックしていただけると、Answerが現れる仕組みになっています。

そしてアコーディオンを閉じるときはもう一度Question部分をクリックしていただくか、現れたAnswer部分をクリックしていただいても閉じます。

HTML

<div class="accordion">
  <input type="checkbox" id="check1" class="accordion-hidden">
  <label for="check1" class="accordion-open">Question1</label>
  <label for="check1" class="accordion-close"> Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1</label>

  <input type="checkbox" id="check2" class="accordion-hidden">
  <label for="check2" class="accordion-open">Question2</label>
  <label for="check2" class="accordion-close">Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2</label>

  <input type="checkbox" id="check3" class="accordion-hidden">
  <label for="check3" class="accordion-open">Question3</label>
  <label for="check3" class="accordion-close">Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3</label>

  <input type="checkbox" id="check4" class="accordion-hidden">
  <label for="check4" class="accordion-open">Question4</label>
  <label for="check4" class="accordion-close">Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4</label>
</div>

チェックボックスには「id」を設定し、質問部分と回答部分を作成するlabel要素にはチェックボックスのidと同じ値を「for」に設定し紐づけをしておきます。

これにより質問部分と回答部分、どちらをクリックしてもチェックボックスにはチェックが入るようになります。

HTMLを記述するうえでのポイントはチェックボックスを先頭にもってきて、その後にlabel要素を使って質問部分と回答部分を作成することです。

この順番の理由ですが、CSSでデザインを設定する際にチェックボックスを起点にして「隣接セレクタ」を使用します。

「隣接セレクタ」は起点となる要素の後続の要素を指定するセレクタです。

今回作成するアコーディオンメニューではチェックボックスへのチェックをCSSのcheckedを使って監視しており、チェックをきっかけにチェックボックスの後続の要素に対してデザインを設定していく為、チェックボックスが先頭になります。

CSS

*,
*::after,
*::before {
  box-sizing: border-box;
}

.accordion {
  width: 500px;
  max-width: 100%;
}

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

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

------------------------------*/
/* チェックボックスを非表示にする */
.accordion-hidden{
  display: none;
}

/* Question部分 */
.accordion-open {
  display: block;
  padding: 10px;
  background: #52a261;
  cursor: pointer;
  margin: 5px 0;
  font-weight: 700;
}

/* Answer部分は最初は表示しない */
.accordion-close {
  display: block;
  height: 0;
  overflow: hidden;
  padding: 0;
  opacity: 0;
  transition: 0.5s;/* 表示速度の設定 */
}

/* チェックボックスにチェックが入ったらAnswer部分を表示 */
.accordion-hidden:checked + .accordion-open + .accordion-close {
  height: auto;
  opacity: 1;
  padding: 10px;
  background: #55acee;
  font-weight: 700;
}

チェックボックスは表示しておく必要はないので「display: none」で非表示にします。

質問部分のlabel要素は高さを0にして、かつoverflow: hiddenにすることで非表示にしておきます。

そしてcheckedを利用してチェックボックスへのチェックが入ったら質問部分が表示されるようにします。

このCSSを見て

ゆんつ
回答部分をdisplay:noneして、チェックが入ったらdisplay:blockにすればいいんんじゃないの?

と思うかもしれませんが、その方法だと回答部分をフワッと表示させることができずいきなり表示されてしまいます。

display:none; → display: block;にした場合

See the Pen accordion4 by konpure (@yuntu) on CodePen.

表示をフワッとさせるためにheight:0やoverflow: hiddenを使って回答部分を非表示にしているのです。

以上がHTMLとCSSだけで作る基本的なアコーディオンメニューです。

アイコンをつけて開閉状態がが解りやすいようにする

先ほどのアコーディオンメニューでは少し味気ないため、アコーディオンメニューが閉じている時は「+」、開いている時は「-」というデザインにしてみたいとおもいます。

See the Pen PoPovgj by konpure (@yuntu) on CodePen.

QuestionをクリックするとAnswerが開いて、「+」のアイコンが「-」になります。

Answerを閉じると再び「+」に戻ります。

HTML

<div class="accordion">
  <input type="checkbox" id="check1" class="accordion-hidden">
  <label for="check1" class="accordion-open">Question1</label>
  <label for="check1" class="accordion-close"> Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1</label>

  <input type="checkbox" id="check2" class="accordion-hidden">
  <label for="check2" class="accordion-open">Question2</label>
  <label for="check2" class="accordion-close">Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2</label>

  <input type="checkbox" id="check3" class="accordion-hidden">
  <label for="check3" class="accordion-open">Question3</label>
  <label for="check3" class="accordion-close">Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3</label>

  <input type="checkbox" id="check4" class="accordion-hidden">
  <label for="check4" class="accordion-open">Question4</label>
  <label for="check4" class="accordion-close">Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4</label>
</div>

HTMLは先ほどのものと全く同じです。

CSS

*,
*::after,
*::before {
  box-sizing: border-box;
}

.accordion {
  width: 500px;
  max-width: 100%;
}

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

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

------------------------------*/
/* チェックボックスは非表示 */
.accordion-hidden{
  display: none;
}

/* Question部分 */
.accordion-open {
  display: block;
  padding: 10px;
  background: #52a261;
  cursor: pointer;
  margin: 5px 0;
  font-weight: 700;
  position: relative;/* 変更部分 */
}

/* 開閉状態を示すアイコン+の作成 */
.accordion-open::before,
.accordion-open::after {
  content: '';
  width: 20px;
  height: 3px;
  background: #000;
  position: absolute;
  top: 50%;
  right: 5%;
  transform: translateY(-50%);
}

/* 一本は縦にして+を作る */
.accordion-open::after {
  transform: translateY(-50%) rotate(90deg);
  transition: .5s;
}

/* アコーディオンが開いたら縦棒を横棒にして-にする */
.accordion-hidden:checked + .accordion-open:after {
  transform: translateY(-50%) rotate(0);
}

/* Answer部分 */
.accordion-close {
  display: block;
  height: 0;
  overflow: hidden;
  padding: 0;
  opacity: 0;
  transition: 0.5s;/* 表示速度の設定 */
}

/* チェックボックスにチェックが入ったらAnswer部分を表示する */
.accordion-hidden:checked + .accordion-open + .accordion-close {
  height: auto;
  opacity: 1;
  padding: 10px;
  background: #55acee;
  font-weight: 700;
}

先ほどとの違いは、+マークの位置調整の基準にするためにQuestion部分に「position: relative」を設定したことと、疑似要素を設定して位置調整を行い「+」マークを作ったことです。

また、checkedによりチェックボックスを監視し、チェックが入ったら「+」の縦棒の角度を0にして横棒にして「-」に見えるようにしてあります。

以上がアコーディオンの開閉状態を示す「+」アイコンの設定方法です。

ゆんつ
簡単!

QとAを付ける

タイトル部分に以下のような感じで「Q」と「A」をつけます。

See the Pen accordion3 by konpure (@yuntu) on CodePen.

HTML

<div class="accordion">
  <input type="checkbox" id="check1" class="accordion-hidden">
  <label for="check1" class="accordion-open"><span>Q</span>Question1</label>
  <label for="check1" class="accordion-close"><span>A</span>Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1 Answer1
  </label>

  <input type="checkbox" id="check2" class="accordion-hidden">
  <label for="check2" class="accordion-open"><span>Q</span>Question2</label>
  <label for="check2" class="accordion-close"><span>A</span>Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2 Answer2</label>

  <input type="checkbox" id="check3" class="accordion-hidden">
  <label for="check3" class="accordion-open"><span>Q</span>Question3</label>
  <label for="check3" class="accordion-close"><span>A</span>Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3 Answer3</label>

  <input type="checkbox" id="check4" class="accordion-hidden">
  <label for="check4" class="accordion-open"><span>Q</span>Question4</label>
  <label for="check4" class="accordion-close"><span>A</span>Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4 Answer4</label>
</div>

これまでのHTMLとの違いはQuestion部分にspanタグで囲んだ「Q」、Answer部分にspanタグで囲んだ「A」を追加しただけです。

CSS

*,
*::after,
*::before {
  box-sizing: border-box;
}

.accordion {
  width: 500px;
  max-width: 100%;
}

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

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

------------------------------*/
/* チェックボックスは非表示 */
.accordion-hidden{
  display: none;
}

/* Question部分 */
.accordion-open {
  display: block;
  padding: 10px 10px 10px 70px;
  background: #52a261;
  cursor: pointer;
  margin: 5px 0;
  font-weight: 700;
  position: relative;/* 変更部分 */
}

/* 開閉状態を示すアイコン+の作成 */
.accordion-open::before,
.accordion-open::after {
  content: '';
  width: 20px;
  height: 3px;
  background: #000;
  position: absolute;
  top: 50%;
  right: 5%;
  transform: translateY(-50%);
}

/* 一本は縦にして+を作る */
.accordion-open::after {
  transform: translateY(-50%) rotate(90deg);
  transition: .5s;
}

/* QとAのデザイン */
.accordion-open span,
.accordion-close span {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 50px;
  height: 100%;
  background: pink;
  position: absolute;
  text-align: center;
  left: 0;
  top: 0;
}

/* アコーディオンが開いたら縦棒を横棒にして-にする */
.accordion-hidden:checked + .accordion-open:after {
  transform: translateY(-50%) rotate(0);
}

/* Answer部分 */
.accordion-close {
  display: block;
  height: 0;/* 要素の高さは0 */
  overflow: hidden;/* 非表示 */
  padding: 0 0 0 60px;
  opacity: 0;
  transition: 0.5s;/* 表示速度の設定 */
  position: relative;
}

/* チェックボックスにチェックが入ったらAnswer部分を表示する */
.accordion-hidden:checked + .accordion-open + .accordion-close {
  height: auto;
  opacity: 1;
  padding: 10px 10px 10px 70px;
  background: #55acee;
  font-weight: 700;
}

「Q」と「A」の大きさを設定し先頭に来るように位置を調整しただけです。

まとめ

以上がCSSだけで作るアコーディオンメニューです。

原理としては

ラベルとチェックボックスを紐づけて、CSSのcheckedを利用してクリック時のデザインを設定する

ということだけなので、理屈さえわかればそれほど難しくないと思います。

アコーディオンメニューを作るのにjQueryを使う方法もありますが、上記のようにCSSだけで作る方法も頭の片隅に入れておいてもいいかもしれません。

ゆんつ
それでは、またー。