➡️

JavaScript不要!アコーディオンの作り方

2024/07/17に公開


上記のようなアコーディオンを作ろうとしてGoogleで検索をすると、<div><input>を使ったものが多く見つかります。
divinputを使うと、セットでJavaScriptを使わなければならない…JavaScripがあまり得意ではない・時間をあまりかけたくないと思う方も多いのではないでしょうか。

しかし<details><summary>を使うと、簡単&以下のメリットがあります。

  • アクセシビリティ対策になる
  • 構造がわかりやすい、読みやすいコードになる
  • JavaScript不要で開閉ができる

今回は<details><summary>タグを使って、JavaScript不要でアコーディオンを作る方法を紹介します。

HTMLとCSS

結論のHTMLとCSSです。
下の方で詳細に解説をします。

HTMLはリセットCSSを読み込んで使用すると、崩れがないです。

    <details>
      <summary class="summary">
        <div class="summary__inner">
          <p class="summary__text">
            質問のテキスト質問のテキスト<br />質問のテキスト質問のテキスト
          </p>
          <span class="summary__arrow"></span>
        </div>
      </summary>
      <div class="answer">
        <div class="answer__inner">
          <p class="answer__text">回答のテキスト回答のテキスト<br>回答のテキスト回答のテキスト</p>
        </div>
      </div>
    </details>
/* 見やすくする用 */
details{
  max-width: 840px;
  margin: 0 auto;
}

/* Qのテキスト */
.summary {
  position: relative;
  display: block;
  background-color: #f5f5f5;
  cursor: pointer;
}
.summary__inner{
  padding: 30px;
}
.summary__text{
  margin-left: 40px;
}


/* Aのテキスト */
.answer{
  position: relative;
  display: block;
  background-color: #f5f5f5;
  cursor: pointer;
}
.answer__inner{
  padding: 30px;

}

.answer__text{
  margin-left: 40px;
}


/* 装飾用 */
/* iOSで表示されるデフォルトの三角形アイコン削除用 */
.summary::-webkit-details-marker {
  display: none;
}

.summary::before{
  content: "Q";
  position: absolute;
  top: 50%;
  left: 4%;
  transform: translateY(-50%);
  width: 30px;
  height: 30px;
  color: #ffffff;
  background-color: skyblue;
  border-radius: 50%;
  line-height: 30px;
  text-align: center;
  font-weight: bold;
}
.answer::before{
  content: "A";
  position: absolute;
  top: 50%;
  left: 4%;
  transform: translateY(-50%);
  width: 30px;
  height: 30px;
  color: #ffffff;
  background-color: pink;
  border-radius: 50%;
  line-height: 30px;
  text-align: center;
  font-weight: bold;
}

/* 質問文右の矢印 */
.summary__arrow{
  position: absolute;
  top: 0;
  right: 30px;
  bottom: 0;
  display: block;
  height: 15px;
  margin: auto;
  background-color: #333333;
  aspect-ratio: 1/cos(30deg);
  clip-path: polygon(100% 13%, 50% 80%, 0 13%, 5% 0, 50% 60%, 95% 0);
  transition: 0.4s;
}
/* 質問が開かれたら矢印を回転 */
details[open] .summary .summary__arrow{
  transform: rotate(180deg);
}

HTML

detailsタグの中に、summaryがあれば最低限の動きは再現できます。
CSSもJavaScriptも書かなくても、矢印マークと開閉が自動でつきます。

    <details>
      <summary>質問です</summary>
      回答です
    </details>

サンプルでは、装飾のためにclassを追加しています。また、開閉を示すアイコンとしてsummary__arrowも置きました。
擬似要素で矢印を再現すればいいのに!と思いますがこれには理由があるのでCSSのほうで解説します。

CSS

背景色をつけたり、質問・回答文の先頭に丸いアイコンをつけたりしています。
さらに、質問文の末尾には矢印アイコンをつけました。

/* 質問文右の矢印 */
.summary__arrow{
  position: absolute;
  top: 0;
  right: 30px;
  bottom: 0;
  display: block;
  height: 15px;
  margin: auto;
  background-color: #333333;
  aspect-ratio: 1/cos(30deg);
  clip-path: polygon(100% 13%, 50% 80%, 0 13%, 5% 0, 50% 60%, 95% 0);
  transition: 0.4s;
}
/* 質問が開かれたら矢印を回転 */
details[open] .summary .summary__arrow{
  transform: rotate(180deg);
}

これは、開いたら矢印を回転させたいためです。
擬似要素で矢印を作らなかった理由は、iOSの場合transitionが効かないためです。

ほかにもiOS用にデフォルトの三角形アイコンを削除するCSSを入れています。

/* iOSで表示されるデフォルトの三角形アイコン削除用 */
.summary::-webkit-details-marker {
  display: none;
}

ちなみに、これを入れないとこのように三角形が表示されてしまいます!!

まとめ

CSS・JavaScript不要で簡単にアコーディオンを作成できました。
今回、矢印を作るのに使ったclip-pathについて、別の記事で後日まとめます。
今まで三角形を作る時はborderを使っていたのですが、 clip-pathを使うととても簡単に矢印を作れました!!

Discussion