details要素とsummary要素でアコーディオン(折り畳み)を作る方法

2023年 2月 8日 Posted 藤原(フロントエンドエンジニア)

よくある質問ページや、Q&A、商品情報等の詳細をアコーディオン(折り畳み)でコーディングする際、制作する人によって色々な実装方法があると思います。JavaScript(jQueryを含む)を使って作ることも多いですね。今回はdetails要素とsummary要素を使用して作ってみようと思います。

折りたたみ表示でよく見るコーディングについて

ネットで色々と調べものをしていると出てくる「よくある質問」ページ。
どのようなコーディングをしているのかソースを調べてみました。

dt要素とdd要素 dt要素(質問)をクリックで、dd要素(答え)を表示
ul要素やol要素 li要素内に質問と答えをコーディング
div要素とp要素 p要素で質問と答えをコーディング
h要素とdiv要素 h要素(質問)をクリックで、div要素(答え)を表示
input要素とdiv要素 input要素(質問)をクリックで、div要素(答え)を表示
buttun要素とdiv要素 buttun要素(質問)をクリックで、div要素(答え)を表示

私自身も過去Q&Aページを作る際、dt要素・dd要素を用いて実装したことがあります。
作成する際、この中に含まれる意味が、dtは用語、ddが用語に対する説明としてコーディングするのが意味として近いものと思い、この要素を使用していました。

details要素とsummary要素とは

HTML 5.1 で勧告されて、HTML Living Standard で標準となっている要素です。

details要素

details要素は、備考や操作手順などの詳細情報を示すときに使います。
detailsの子要素としてsummaryを用いる場合は、summaryの内容が詳細情報の要約になります。

summary要素

summary要素は、summaryの親要素となるdetailsの内容のキャプション、説明を表す際に使います。summary要素は、details要素の最初の子としてのみ使用できます。

サポート状況

主要ブラウザ(IE・Opera Miniを除く)で問題なく使用できます。

なぜdetails要素とsummary要素で作るのか

コンテンツの意味をHTML要素で表現することができる

div要素やspan要素で「質問内容」とマークアップしてもそれは意味的要素を持たないものになります。p要素で「質問内容」とマークアップしてもテキストの段落として認識されます。summary要素に「質問内容」とマークアップすると、details要素の要約、キャプション、説明として認識されます。

JavaScript(jQueryを含む)に頼らず、少しのCSSの調整だけで作成することができる

以下の様に初期表示され、「質問内容の表示」をクリックで表示・非表示を切り替えることができます。詳細には複数の要素が配置できます。p要素だけではなく、ul要素やol要素など使っても大丈夫です。

質問内容の表示

答えが表示

<details>
	<summary>質問内容の表示</summary>
	<p>答えが表示</p>
</details>

表示されるとdetailsにopen属性が付与されます。
「<details open>」と記述することで、はじめからアコーディオンを開いておくことができます。

質問内容の表示

答えが表示

<details open>
	<summary>質問内容の表示</summary>
	<p>答えが表示</p>
</details>

特別なケアをしなくてもアクセシビリティ面で最適化されている

コンテンツの折り畳みと展開は、スクリーンリーダーおよびキーボード操作のみでも利用できます。

キーボード操作

Tabキーでsummary要素を選択、Enterキーを押下すると、詳細内容が展開されます。

スクリーンリーダー

スクリーンリーダーのNVDAを起動し、タブフォーカスとエンターキー・スペースキーでの開閉操作ができます。また、キーボードで操作すると、以下の様に読み上げられます。

参考

CSSで見た目を調整してみる

以下の点に気を付けて調整してみました。

注意点

上記を考慮して、以下の設定をします。

summary {
	list-style: none;
	cursor: pointer;
}

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

上記を含め、見た目を変更してみました

開閉時の動きを滑らかにしてみたり、色々変更しても良いかと思います。

質問内容の表示

答えが表示

質問内容の表示

答えが表示

質問内容の表示

答えが表示

  • 答えが表示
  • 答えが表示

HTML

<div class="accordion-test">
		<details>
			<summary>質問内容の表示</summary>
			<div class="contents">
				<p>答えが表示</p>
			</div>
		</details>
		<details>
			<summary>質問内容の表示</summary>
			<div class="contents">
				<p>答えが表示</p>
			</div>
		</details>
		<details>
			<summary>質問内容の表示</summary>
			<div class="contents">
				<p>答えが表示</p>
				<ul>
					<li>答えが表示</li>
					<li>答えが表示</li>
				</ul>
			</div>
		</details>
</div>

CSS

.accordion-test summary{
	position: relative;
	list-style: none; /* デフォルトの三角形アイコンを消します */
	padding: 15px 45px 15px 25px;
	border:1px solid #000474;
	cursor: pointer; /* ポインターを指さしマークに変更 */
}

.accordion-test summary::-webkit-details-marker {
	display: none; /* Safariで表示されるデフォルトの三角形アイコンを消します */
}

.accordion-test summary::after{
	position: absolute;
	width: 15px;
	height: 15px;
	top: calc(50% - 10px);
	right: 25px;
	border-right: 4px solid #000474;
	border-bottom: 4px solid #000474;
	box-sizing: border-box;
	content: "";
	transform: rotate(45deg);
	transition: top 0.4s ease-out, transform 0.4s ease-out;
}

.accordion-test details[open] summary::after{
	top: calc(50% - 5px);
	transform: rotate(-135deg);
}

.accordion-test .contents{
	padding: 15px 45px;
	background:#E8ECF7;
}

まとめ

いかがでしたか?コーディングが簡単になり、アクセシビリティの質をあげることができるdetails要素とsummary要素。ぜひぜひ使ってみてください!