「HTML」と「CSS」のみで実装するアコーディオン表示

「HTML」と「CSS」のみで実装する【JavaScriptを使用しない】アコーディオン表示

よくある質問や、メニューリストなどコンテンツをシンプルな表示にしたいときに用いられる、アコーディオン表示の構築は一見難しく見えますが、「HTML」と「CSS」のみで比較的簡単に実装することが可能です。

この記事では、HTMLのdetails、summaryを使用した方法と、input、labelを使用する2種類の方法をご紹介したいと思います。

月額99円から。容量最大1TB!ブログ作成におすすめのWordPressテーマ「Cocoon」も簡単インストール

アコーディオン表示とは メリット・デメリット

アコーディオン表示は、項目のタイトルをクリックすることで、隠していた詳細内容を開閉表示させるテクニックで、その開閉する様子が、アコーディオンの蛇腹部分を連想することから名付けられました。

アコーディオン表示を実装する箇所としては、よくある質問や、ナビゲーションメニューなど表示内容や一覧を多数掲載する必要がある部分で、表示領域をコンパクトに抑えたい場合に非常に有効です。

しかし、最初からコンテンツが隠された状態であるので、ユーザーが必要な情報に気づかずにたどり着かない、一覧で情報を表示させることが出来ず一つ一つクリックするというアクションが必要になる、などのデメリットが存在しますので、開閉可能な部分にはわかりやすいアイコンを設置するなど、アコーディオン表示に向いている内容なのか、導入にはユーザビリティーを考慮する必要があります。

details、summaryでアコーディオン表示を実装する

ここからは、実際にアコーディオン表示を実装する方法について見ていきます。記事の最初でも述べましたが、比較的容易に実装することが可能です。

details、summaryの方法では、HTMLのタグを記述するのみで、複雑なコーディングを必要とせずほぼ構築が出来てしまいます。

HTMLマークアップ

detailsタグの中に、summaryタグを設置し、summaryタグの中身がクリックさせる項目のタイトルとなり、details以下のそれ以外の部分は非表示となります。

<details>
  <summary>項目のタイトル</summary>
 非表示部分です。
</details>
<details>
  <summary>項目のタイトル</summary>
 非表示部分です。
</details>
<details>
  <summary>項目のタイトル</summary>
 非表示部分です。
</details>

See the Pen accordion details - summary1 by web-basic-archive (@web-basic-archive) on CodePen.

summaryタグのテキストの左側には、デフォルトで三角形のアイコンが表示されます。テキスト部分をクリックすると隠された部分が表示されます。

装飾例とアイコンアニメーション

もう少し、アコーディオン表示とわかるようにCSSで装飾し、開閉時にアイコンをアニメーションさせていきましょう。

<details>
  <summary>項目のタイトル<span class="icon"></span></summary>
  <div>コンテンツ</div>
</details>
<details>
  <summary>項目のタイトル<span class="icon"></span></summary>
  <div>コンテンツ</div>
</details>
<details>
  <summary>項目のタイトル<span class="icon"></span></summary>
  <div>コンテンツ</div>
</details>

span要素で矢印アイコンを作ります。

details {
  border: 1px solid #555;
  margin-bottom: 10px;
}
summary {
  padding: 1em;
  background: #eee;
  font-weight: bold;
  cursor: pointer;
  list-style: none;
  position: relative;
}

/* Safari対応 デフォルトの三角形アイコン非表示 */
details summary::-webkit-details-marker {
  display: none;
}

div {
  padding: 1em;
}

.icon {
  display: block;
  position: absolute;
  right: 20px;
  top: 50%;
  width: 24px;
  margin-left: 6px;
  flex-shrink: 0;
  transform-origin: center 43%;
  transition: transform 0.5s;
}

/* アイコンの三角矢印 */
.icon::before,
.icon::after {
  content: "";
  position: absolute;
  display: block;
  width: 15px;
  height: 3px;
  background-color: #000;
}

.icon::before {
  left: 0;
  transform: rotate(45deg);
}

.icon::after {
  right: 0;
  transform: rotate(-45deg);
}

/* アコーディオン表示の際に回転する */
details[open] .icon {
  transform: rotate(180deg);
}

デフォルトの三角を非表示にします。list-style:none;

Safariでは効かない場合があるので、15行目の記述を追加します。

36行目 新しくspanで作った三角アイコン .iconを開閉時に180度回転するアニメーションを追加します。details要素は、summaryをクリック後の表示時に、open属性が付与される仕様になっているので、details[open]で指定します。

コードサンプル

See the Pen accordion details - summary2 by web-basic-archive (@web-basic-archive) on CodePen.

メリット、デメリット

details、summaryタグで構築する場合は、HTMLのマークアップも非常にシンプルになり、かつアクセシビリティの面でも非表示時のスクリーンリーダー、ページ内検索の対応も可能なので、大きなメリットがあります。

しかし、コードサンプルを見ていただいても分かるように開閉時に隠れていたコンテンツが瞬時に表示されてしまい、滑らかなアニメーションが設定できません。この方法でトランジションを効かせるアニメーションを行うには、JavaScriptでの制御が必要になってきます。

JavaScriptを使用せずに、CSSでアニメーションを設定する場合は次の、input、labelを使用する方法をお試しください。

input、labelでアコーディオン表示を実装する

アコーディオン表示をJavaScriptを使用せずに構築する方法でスタンダードだったのが、このinput、label要素を用いる手法ではないでしょうか。

inputのチェックボックス型を使用して、クリックされたかどうかを判定します。そして、label要素と紐付けさせることでlabelのテキストをクリックしてもチェックがつくようになります。これを利用して、アコーディオンの動作をCSSで設定していく方法です。

HTMLマークアップ

<div>
<input type="checkbox" id="check1">
<label class="title" for="check1">項目のタイトル</label>
<div class="content">
<p>コンテンツ</p>
</div>
</div>
<div>
<input type="checkbox" id="check2">
<label class="title" for="check2">項目のタイトル</label>
<div class="content">
<p>コンテンツ</p>
</div>
</div>
<div>
<input type="checkbox" id="check3">
<label class="title" for="check3">項目のタイトル</label>
<div class="content">
<p>コンテンツ</p>
</div>
</div>

label要素のfor属性にinput要素のidを指定して、各項目ごとに紐づけを行います。

CSSの設定

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

label {
  padding: 1em;
  background: #eee;
  display: block;
  font-weight: bold;
  position: relative;
  cursor: pointer;
}

/*三角矢印アイコン*/
.icon {
  display: block;
  position: absolute;
  right: 20px;
  top: 50%;
  width: 24px;
  margin-left: 6px;
  flex-shrink: 0;
  transform-origin: center 43%;
  transition: transform 0.5s;
}
.icon::before,
.icon::after {
  content: "";
  position: absolute;
  display: block;
  width: 15px;
  height: 3px;
  background-color: #000;
}
.icon::before {
  left: 0;
  transform: rotate(45deg);
}
.icon::after {
  right: 0;
  transform: rotate(-45deg);
}

.wrap {
  border: 1px solid #000;
  margin-bottom: 10px;
}

/*コンテンツ初めは非表示*/
.content {
  max-height: 0;
  opacity: 0;
  visibility: hidden;
  transition: 0.5s;
  overflow: hidden;
}
p {
  margin: 0;
  padding: 1em;
}

/*クリックするとコンテンツ表示*/
input:checked ~ .content {
  max-height: 100px;
  opacity: 1;
  visibility: visible;
}

/* アコーディオン表示の際に三角回転 */
input:checked ~ label .icon {
  transform: rotate(180deg);
}

2行目:inputは、チェックボックスの機能のみ使うので非表示にしておきます。

51行目:コンテンツ部分も初めは隠しておくので、opacity、visibility、overflowなどを設定し非表示にします。アコーディオンの伸び縮みするアニメーションを実現するために、max-heightを0、またtransitionの設定をしておきます。

64行目:labelをクリックするとforで紐づいたinput属性にチェックが入り、疑似クラスcheckedが付与されます。この特性を利用し、関節セレクタ(~)を使用し、チェックが入ったinput要素以降の. contentを表示する設定を記述します。また、max-heightを設定することで、隠れていた部分が伸びて表示されるアニメーションになります。

コードサンプル

See the Pen accordion input-label by web-basic-archive (@web-basic-archive) on CodePen.

アコーディオン表示実装のまとめ

今回は、JavaScriptを使用せずにアコーディオン表示を実装する方法を2種類お伝えしましたが、それぞれメリット・デメリットがありますので、サイトの要件等に合わせて選択してみてください。

参考にしたサイト

detailsとsummaryタグで作るアコーディオンUI - アニメーションのより良い実装方法

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

Follow me!