クリックで開閉するアコーディオンをCSSだけで作る方法を2つご紹介します。
どちらもコピペOKなので、ご活用ください。
関連記事:【コピペOK】jQueryでアコーディオンを作る方法
detailsタグを使うパターン
まずは<details>を使うパターンです。後に紹介する<input>を使うパターンより、こちらの方がコードはシンプルです。
早速コードを見てみましょう。HTMLとCSSはそれぞれ下記になります。
<details class="accordion">
  <summary class="accordion__summary">アコーディオンの見出し</summary>
  <div class="accordion__detail">
    <p class="accordion__text">アコーディオンの中身</p>
  </div>
</details>.accordion {
  margin: 2em 0;
}
.accordion__summary {
  display: block;
  background: #b2e5ff; /* 見出しの背景色 */
  font-weight: bold;
  position: relative;
  list-style: none; /* 矢印を消す */
  cursor: pointer;
  padding: 10px 38px 10px 10px;
}
.accordion__summary::-webkit-details-marker {
  display: none;
}
.accordion__summary::after {
  content: "+";
  font-size: 1.4em; /* 記号のサイズ */
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
}
.accordion[open] .accordion__summary::after {
  content: "−";
}
.accordion__detail {
  padding: 4px 10px;
  margin: 10px 0;
}
.accordion__text {
  margin: 0;
}コードの解説
<details>は折りたたみ要素をHTMLだけで実装できるタグです。昔はアコーディオンを実装するためにはJavaScriptを書いたり後述するように<input>を活用したりする必要がありましたが、このタグの登場で状況が変わりました。
<details>の使い方はシンプルで、全体を<details>で囲った上で見出しとして使いたい要素に<summary>を使うだけです。
CSSを用いずともアコーディオン自体は実装できますが、スタイルを調整するために上述の例ではCSSを記述しています。
ポイントとしては、<details>の標準スタイルでは三角形アイコンが見出しテキストの左側に表示されますが、それを消した上で、アコーディオンの右端に開閉に応じて表示が切り替わるプラスマイナスを設置しています。
三角形アイコンはlist-styleで指定されているため、list-style: none;で消すことができます。
その上で、プラスマイナスは通常の擬似要素で表示させますが、開閉に応じて記号を切り替えるためにopenの属性セレクタを使っています。
<details>タグは「開いている状態」を表すopen属性を持つことができるので、この属性セレクタを使用することでアコーディオンが開いているときに適用させるスタイルを定義できます。
IE対応
<details>タグは便利ですがIEは対応していない点が要注意です。
IE環境でも<details>を機能させたい場合は、以下のpolyfillを使います。
<script src="https://cdn.jsdelivr.net/npm/details-polyfill@1.2.0/index.min.js"></script>このpolyfillを使うと、<summary>がdisplay: inline;になるため、デザインを維持するためにはdisplay: block;を当てる必要があります。
また、デフォルトの三角形アイコンがlist-styleでなく擬似要素による実装になるため、content: "";で非表示にします。
.accordion__summary {
  display: block;
}
.accordion__summary::before {
  content: "";
}inputタグを使うパターン
<details>は便利ですが、polyfillを使わずともより広い環境に対応できるよう<input>を活用して実装するパターンも考えられます。
HTMLとCSSは以下の通りです。
<div class="accordion">
  <input type="checkbox" id="label-1">
  <label class="accordion__summary" for="label-1">アコーディオンの見出し</label>
    <div class="accordion__detail">
      <p class="accordion__text">アコーディオンの中身</p>
    </div>
</div>.accordion {
  margin: 2em 0;
}
.accordion__summary {
  background: #b2e5ff; /* アコーディオンの見出しの背景色 */
  font-weight: bold;
  position: relative;
  display: block;
  cursor: pointer;
  padding: 10px 38px 10px 10px;
}
.accordion__summary::after {
  content: "+";
  font-size: 1.4em; /* 記号のサイズ */
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
}
.accordion input:checked ~ .accordion__summary::after {
  content: "−";
}
.accordion input {
  display: none;
}
.accordion__detail {
  display: none;
  background: #fff;
  padding: 4px 10px;
  margin: 10px 0;
}
.accordion input:checked ~ .accordion__detail {
  display: block;
}
.accordion__text {
  margin: 0;
}コードの解説
このパターンでは、下記の構成でアコーディオンを実装しています。
- <label>で実装した見出し部分をクリックすることで、- <input>にチェックが入るようにする
- 隣接セレクタを活用することで、<input>にチェックが入ったときだけアコーディオンの中身を表示させるためのCSSが当たるようにする
まず、<input>のid=""と<label>のfor=""に同じ値を入れることで、「<label>がクリックされると<input>にチェックが入る」という状態を作れます。
さらに、<input>は開閉の仕組みのためにだけ用いるため、display: none;で非表示にしておきます。
そして、兄弟セレクタ(~)を用いて.accordion input:checked ~ .accordion__detailを記述することで、「ラベルがクリックされて<input>にチェックが入ったら、それに隣接するアコーディオンの中身部分にこのCSSを当てる」という指定ができます。
そのセレクタに対してdisplay: block;を書くことで、元々当てておいたdisplay: none;が打ち消されてアコーディオンの中身が表示されます。

