アコーディオンをHTMLとCSSだけで実装しよう

目次
  1. HTMLの基本の書き方
  2. summaryのアイコンを消す
  3. 見出し部分の装飾を当てる方法
    1. アイコンを追加する
    2. 開閉時にアイコンを切り替える
  4. コンテンツ部分の装飾を当てる方法
  5. 排他的なアコーディオンにする
  6. detailsとsummary要素を使うメリット

アコーディオンの表現をJavaScriptを使わずにHTMLとCSSで実装していきましょう。

HTMLの基本の書き方

detailsとsummary要素を使うことでアコーディオンの元となる表現が可能になります。summaryを押すことでその他の要素を開閉できます。

HTML <details> 詳細折りたたみ要素 – HTML | MDN

<details>
	<summary>質問が入ります。質問が入ります。質問が入ります。質問が入ります。質問が入ります。</summary>
	<div class="details__contents">
		<p>回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。</p>
	</div>
</details>

開くとdetailsにopen属性が付与されます。

<details open>
	<summary>質問が入ります。質問が入ります。質問が入ります。質問が入ります。質問が入ります。</summary>
	<div class="details__contents">
		<p>回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。</p>
	</div>
</details>

summaryのアイコンを消す

summaryのdisplayにはlist-itemが指定されています。アイコンを消したい場合はdisplayの値を変えることで消すことが可能です。

summary {
	display: block;
}

また、Safariでは以下の通り::-webkit-details-markerの擬似要素で表現されています。不要でしたら消しましょう。

summary::-webkit-details-marker {
	display: inline-block;
	width: 0.66em;
	height: 0.66em;
	margin-inline-end: 0.4em;
}

↓

summary::-webkit-details-marker {
	display: none;
}

見出し部分の装飾を当てる方法

見出しはsummaryに装飾を当てることができます。フレージングコンテンツに相当しますが、見出し(h1〜h6)も交ぜることが可能です。

HTML <summary> 概要明示要素 – HTML | MDN

summary {
	display: block;
	padding: 10px;
}

アイコンを追加する

summary {
	display: block;
	padding: 12px;
	position: relative;

	&::after {
		content: "↓";
		position: absolute;
		inset-inline-end: 12px;
		inset-block-start: 50%;
		translate: 0 -50%;
	}
}

開閉時にアイコンを切り替える

開いた時にdetailsに追加される[open]属性を活用して開閉の状態に合わせたCSSを指定しましょう。

details {
	--animation-duration: 0.3s;
}

summary {
	&::after {
		transition: rotate 0.3s;
	}
}

details[open] {
	summary {
		&::after {
			rotate: 180deg;
		}
	}
}

コンテンツ部分の装飾を当てる方法

detailsのコンテンツ部分はsummary以外が相当します。そのコンテンツ部分は::details-contentの擬似要素で指定することが可能です。

活用例としては、開閉する際にアニメーションを当てることが可能になります。実装例としては以下の通りです。interpolate-size: allow-keywords;を指定することで、block-sizeの0とautoをアニメーションしながら切り替えることができます。

details {
	--animation-duration: 0.3s;
}

details::details-content {
	block-size: 0;
	overflow: hidden;
	transition: block-size var(--animation-duration), content-visibility var(--animation-duration) allow-discrete;
	interpolate-size: allow-keywords;
}

details[open]::details-content {
	block-size: auto;
}

::details-content CSS pseudo-element – CSS | MDN

interpolate-size CSS property – CSS | MDN

排他的なアコーディオンにする

detailsにname属性を指定して同じ値を指定すると、排他的なアコーディオンにすることが可能です。以下の例ではnameに同じqaを指定しています。

<details name="qa">
	<summary>質問が入ります。質問が入ります。質問が入ります。質問が入ります。質問が入ります。</summary>
	<div class="details__contents">
		<p>回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。</p>
	</div>
</details>
<details name="qa">
	<summary>質問が入ります。質問が入ります。質問が入ります。質問が入ります。質問が入ります。</summary>
	<div class="details__contents">
		<p>回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。</p>
	</div>
</details>
<details name="qa">
	<summary>質問が入ります。質問が入ります。質問が入ります。質問が入ります。質問が入ります。</summary>
	<div class="details__contents">
		<p>回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。</p>
	</div>
</details>

detailsとsummary要素を使うメリット

隠れている部分がブラウザの検索機能に反応するようになります。以下の場合に「回答」と検索すると、自動的に隠れている部分が開いてテキストがあることを教えてくれます。

<details>
	<summary>質問が入ります。質問が入ります。質問が入ります。質問が入ります。質問が入ります。</summary>
	<div class="details__contents">
		<p>回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。回答が入ります。</p>
	</div>
</details>

WordPressでお悩みの方はお気軽にご相談ください。

ちょっとしたお困り事からサイト全体のリニューアルのようなご依頼まで、お悩みに応じて柔軟に対応いたします。

この記事を書いた人

はにわまん

HPcode代表。300件以上のWordPress案件を対応してきました。ちょっとしたWordPressのカスタマイズからブロックテーマでのリニューアルまで。更新できるWordPressサイトが好きです。