details 要素を使用したアコーディオン UI の実装サンプル

GitHub (burnworks/details-accordion-ui-sample)

サンプル 01

よくある質問と答え(FAQ)のようなコンテンツでよくみるアコーディオン UI のサンプル

質問に対してここに答えを入れるイメージ。リストされている質問の数がとても多い場合などには、答え部分を閉じておくことで、質問を一覧できていいかもしれないけど、項目が少ないならあんまり閉じておく意味はないかもね。

今一番欲しいものは何ですか?

税引き後金額で5000兆円欲しいけど、妥協して10億円でもいい。

好きな食べ物は何ですか?

グミが好きです。でもゼリーの方がもっと好きです。

1つの項目を開いたら、他の項目は閉じてほしいんだけど

name 属性を使うとできるよ。サンプル 02 をみてね。でも Firefox は今のところ対応していないよ。

最初から開いておくことはできないの?

details 要素に open 属性をつけると、初期状態が開いた状態になるよ。

アクセシビリティ的には大丈夫なの?

details 要素で実装しておけば基本的には大丈夫だから気にすんな。下手に JavaScript で実装する方がダルいよ。

ソースコード

HTML
<div class="details-sample-01">
    <h2 class="details-sample-header">サンプル 01</h2>
    <div class="details-wrap">
        <!--↓ここからがひとつのブロック↓-->
        <details>
            <summary>
                <span class="summary-text">よくある質問と答え(FAQ)のようなコンテンツでよくみるアコーディオン UI のサンプル</span>
                <span class="summary-icon" aria-hidden="true">
                    <svg class="open-icon" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M12 6v12m6-6H6" />
                    </svg>
                    <svg class="close-icon" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M18 12H6" />
                    </svg>
                </span>
            </summary>
            <div class="details-text">
                <p>質問に対してここに答えを入れるイメージ。リストされている質問の数がとても多い場合などには、答え部分を閉じておくことで、質問を一覧できていいかもしれないけど、項目が少ないならあんまり閉じておく意味はないかもね。</p>
            </div>
        </details>
        <!--↑ここまでがひとつのブロック↑-->
    </div>
</div>
CSS
/*---
下記 CSS はあくまでサンプルです。
他のCSSやブラウザの標準スタイルとの関係で調整が必要かもしれません
---*/

.details-sample-01 {
    margin-left: auto;
    margin-right: auto;
    max-width: 64rem;
}

.details-sample-01 .details-sample-header {
    font-size: 1.5rem;
    font-weight: 700;
    color: rgb(17 24 39 / 1);
}

.details-sample-01 .details-wrap {
    margin-top: 2.5rem;
	border-top-width: 1px;
    border-top-style: solid;
	border-color: rgb(17 24 39 / 0.1);
}

.details-sample-01 .details-wrap > :not([hidden]) ~ :not([hidden]) {
	border-top-width: 1px;
    border-top-style: solid;
	border-color: rgb(17 24 39 / 0.1);
}

.details-sample-01 details {
    padding-top: 1.5rem;
    padding-bottom: 1.5rem;
}

.details-sample-01 details summary {
    box-sizing: border-box;
    color: rgb(17 24 39 / 1);
	display: flex;
	width: 100%;
	list-style-type: none;
	align-items: flex-start;
	justify-content: space-between;
}

.details-sample-01 details summary:hover {
    cursor: pointer;
}

.details-sample-01 details summary::-webkit-details-marker {
    display: none;
}

.details-sample-01 details .summary-text {
    width: 100%;
    font-size: 1rem;
    line-height: 1.5rem;
    font-weight: 600;
}

.details-sample-01 details summary > :not([hidden]) ~ :not([hidden]) {
    margin-left: 1.5rem;
}

.details-sample-01 details .summary-icon {
	display: flex;
	height: 1.5rem;
	flex-shrink: 0;
	align-items: center;
	color: rgb(75 85 99 / 1);
}

.details-sample-01 details .summary-icon .open-icon {
    display: block;
    height: 1.5rem;
    width: 1.5rem;
}

.details-sample-01 details .summary-icon .close-icon {
    display: none;
    height: 1.5rem;
    width: 1.5rem;
}

.details-sample-01 details[open] .summary-icon .open-icon {
    display: none;
}

.details-sample-01 details[open] .summary-icon .close-icon {
    display: block;
}

.details-sample-01 details .details-text {
    padding-right: 3rem;
    color: rgb(55 65 81 / 1);
	margin-top: 1.5rem;
}

.details-sample-01 details .details-text p {
	margin: 0;
}

サンプル 02 (排他的動作)

よくある質問と答え(FAQ)のようなコンテンツでよくみるアコーディオン UI のサンプル。

質問に対してここに答えを入れるイメージ。リストされている質問の数がとても多い場合などには、答え部分を閉じておくことで、質問を一覧できていいかもしれないけど、項目が少ないならあんまり閉じておく意味はないかもね。

今一番欲しいものは何ですか?

税引き後金額で5000兆円欲しいけど、妥協して10億円でもいい。

好きな食べ物は何ですか?

グミが好きです。でもゼリーの方がもっと好きです。

1つの項目を開いても、他の項目は閉じないようにしたいんだけど。

details 要素に付いている name 属性を削除しましょう。サンプル 01 をみてね。

ソースコード

HTML
<div class="details-sample-02">
    <h2 class="details-sample-header">サンプル 02</h2>
    <div class="details-wrap">
        <!--↓ここからがひとつのブロック↓-->
        <details name="sample-02">
            <summary>
                <span class="summary-text">よくある質問と答え(FAQ)のようなコンテンツでよくみるアコーディオン UI のサンプル</span>
                <span class="summary-icon" aria-hidden="true">
                    <svg class="open-icon" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M12 6v12m6-6H6" />
                    </svg>
                    <svg class="close-icon" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M18 12H6" />
                    </svg>
                </span>
            </summary>
            <div class="details-text">
                <p>質問に対してここに答えを入れるイメージ。リストされている質問の数がとても多い場合などには、答え部分を閉じておくことで、質問を一覧できていいかもしれないけど、項目が少ないならあんまり閉じておく意味はないかもね。</p>
            </div>
        </details>
        <!--↑ここまでがひとつのブロック↑-->
    </div>
</div>
CSS
/*---
下記 CSS はあくまでサンプルです。
他のCSSやブラウザの標準スタイルとの関係で調整が必要かもしれません
---*/

.details-sample-02 {
    margin-left: auto;
    margin-right: auto;
    max-width: 64rem;
}

.details-sample-02 .details-sample-header {
    font-size: 1.5rem;
    font-weight: 700;
    color: rgb(17 24 39 / 1);
}

.details-sample-02 .details-wrap {
    margin-top: 2.5rem;
	border-top-width: 1px;
    border-top-style: solid;
	border-color: rgb(17 24 39 / 0.1);
}

.details-sample-02 .details-wrap > :not([hidden]) ~ :not([hidden]) {
	border-top-width: 1px;
    border-top-style: solid;
	border-color: rgb(17 24 39 / 0.1);
}

.details-sample-02 details {
    padding-top: 1.5rem;
    padding-bottom: 1.5rem;
}

.details-sample-02 details summary {
    box-sizing: border-box;
    color: rgb(17 24 39 / 1);
	display: flex;
	width: 100%;
	list-style-type: none;
	align-items: flex-start;
	justify-content: space-between;
}

.details-sample-02 details summary:hover {
    cursor: pointer;
}

.details-sample-02 details summary::-webkit-details-marker {
    display: none;
}

.details-sample-02 details .summary-text {
    width: 100%;
    font-size: 1rem;
    line-height: 1.5rem;
    font-weight: 600;
}

.details-sample-02 details summary > :not([hidden]) ~ :not([hidden]) {
    margin-left: 1.5rem;
}

.details-sample-02 details .summary-icon {
	display: flex;
	height: 1.5rem;
	flex-shrink: 0;
	align-items: center;
	color: rgb(75 85 99 / 1);
}

.details-sample-02 details .summary-icon .open-icon {
    display: block;
    height: 1.5rem;
    width: 1.5rem;
}

.details-sample-02 details .summary-icon .close-icon {
    display: none;
    height: 1.5rem;
    width: 1.5rem;
}

.details-sample-01 details[open] .summary-icon .open-icon {
    display: none;
}

.details-sample-01 details[open] .summary-icon .close-icon {
    display: block;
}

.details-sample-02 details .details-text {
    padding-right: 3rem;
    color: rgb(55 65 81 / 1);
	margin-top: 1.5rem;
}

.details-sample-02 details .details-text p {
	margin: 0;
}

サンプル 03 (アイコンが回転)

よくある質問と答え(FAQ)のようなコンテンツでよくみるアコーディオン UI のサンプル。

質問に対してここに答えを入れるイメージ。リストされている質問の数がとても多い場合などには、答え部分を閉じておくことで、質問を一覧できていいかもしれないけど、項目が少ないならあんまり閉じておく意味はないかもね。

今一番欲しいものは何ですか?

税引き後金額で5000兆円欲しいけど、妥協して10億円でもいい。

好きな食べ物は何ですか?

グミが好きです。でもゼリーの方がもっと好きです。

ソースコード

HTML
<div class="details-sample-03">
    <h2 class="details-sample-header">サンプル 03</h2>
    <div class="details-wrap">
        <!--↓ここからがひとつのブロック↓-->
        <details>
            <summary>
                <span class="summary-text">よくある質問と答え(FAQ)のようなコンテンツでよくみるアコーディオン UI のサンプル</span>
                <span class="summary-icon" aria-hidden="true">
                    <svg class="arrow-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" >
                        <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
                    </svg>
                </span>
            </summary>
            <div class="details-text">
                <p>質問に対してここに答えを入れるイメージ。リストされている質問の数がとても多い場合などには、答え部分を閉じておくことで、質問を一覧できていいかもしれないけど、項目が少ないならあんまり閉じておく意味はないかもね。</p>
            </div>
        </details>
        <!--↑ここまでがひとつのブロック↑-->
    </div>
</div>
CSS
/*---
下記 CSS はあくまでサンプルです。
他のCSSやブラウザの標準スタイルとの関係で調整が必要かもしれません
---*/

.details-sample-03 {
    margin-left: auto;
    margin-right: auto;
    max-width: 64rem;
}

.details-sample-03 .details-sample-header {
    font-size: 1.5rem;
    font-weight: 700;
    color: rgb(17 24 39 / 1);
}

.details-sample-03 .details-wrap {
    margin-top: 2.5rem;
	border-top-width: 1px;
    border-top-style: solid;
	border-color: rgb(17 24 39 / 0.1);
}

.details-sample-03 .details-wrap > :not([hidden]) ~ :not([hidden]) {
	border-top-width: 1px;
    border-top-style: solid;
	border-color: rgb(17 24 39 / 0.1);
}

.details-sample-03 details {
    padding-top: 1.5rem;
    padding-bottom: 1.5rem;
}

.details-sample-03 details summary {
    box-sizing: border-box;
    color: rgb(17 24 39 / 1);
	display: flex;
	width: 100%;
	list-style-type: none;
	align-items: flex-start;
	justify-content: space-between;
}

.details-sample-03 details summary:hover {
    cursor: pointer;
}

.details-sample-03 details summary::-webkit-details-marker {
    display: none;
}

.details-sample-03 details .summary-text {
    width: 100%;
    font-size: 1rem;
    line-height: 1.5rem;
    font-weight: 600;
}

.details-sample-03 details summary > :not([hidden]) ~ :not([hidden]) {
    margin-left: 1.5rem;
}

.details-sample-03 details .summary-icon {
	display: flex;
	height: 1.5rem;
	flex-shrink: 0;
	align-items: center;
	color: rgb(75 85 99 / 1);
}

.details-sample-03 details .summary-icon .arrow-icon {
	height: 1.5rem;
	width: 1.5rem;
	transition-property: transform;
	transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
	transition-duration: 150ms;
}

.details-sample-03 details[open] .summary-icon .arrow-icon {
	transform: rotate(180deg);
}

.details-sample-03 details .details-text {
    padding-right: 3rem;
    color: rgb(55 65 81 / 1);
	margin-top: 1.5rem;
}

.details-sample-03 details .details-text p {
	margin: 0;
}

ソースコード

HTML
<div class="details-sample-04">
    <h2 class="details-sample-header">サンプル 04</h2>
    <div class="details-wrap">
        <!--↓ここからがひとつのブロック↓-->
        <details>
            <summary>
                <span class="summary-text">
                    サービス案内    
                </span>
                <span class="summary-icon" aria-hidden="true">
                    <svg class="open-icon" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M12 6v12m6-6H6" />
                    </svg>
                    <svg class="close-icon" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M18 12H6" />
                    </svg>
                </span>
            </summary>
            <div class="details-text">
                <ul>
                    <li>
                        <a href="#">
                            コンテンツへのリンク
                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
                                <path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" />
                            </svg>
                        </a>
                    </li>
                    <li>
                        <a href="#">
                            コンテンツへのリンク
                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
                                <path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" />
                            </svg>
                        </a>
                    </li>
                </ul>
            </div>
        </details>
        <!--↑ここまでがひとつのブロック↑-->
    </div>
</div>
CSS
/*---
下記 CSS はあくまでサンプルです。
他のCSSやブラウザの標準スタイルとの関係で調整が必要かもしれません
---*/

.details-sample-04 {
    margin-left: auto;
    margin-right: auto;
    max-width: 64rem;
}

.details-sample-04 .details-sample-header {
    font-size: 1.5rem;
    font-weight: 700;
    color: rgb(17 24 39 / 1);
}

.details-sample-04 .details-wrap > :not([hidden]) ~ :not([hidden]) {
	border-top-width: 1px;
    border-top-style: solid;
	border-color: rgb(17 24 39 / 0.1);
}

.details-sample-04 .details-wrap {
    margin-top: 2.5rem;
	border-radius: 0.5rem;
    border-style: solid;
	border-width: 1px;
	border-color: rgb(17 24 39 / 0.1);
}

.details-sample-04 details {
    padding: 0;
    margin: 0;
}

.details-sample-04 details summary {
    box-sizing: border-box;
	padding: 1.5rem;
	color: rgb(17 24 39 / 1);
	display: flex;
	width: 100%;
	list-style-type: none;
	align-items: flex-start;
	justify-content: space-between;
}

.details-sample-04 details summary:hover {
    cursor: pointer;
}

.details-sample-04 details summary::-webkit-details-marker {
    display: none;
}

.details-sample-04 details .summary-text {
    width: 100%;
    font-size: 1rem;
    font-weight: 600;
}

.details-sample-04 details summary > :not([hidden]) ~ :not([hidden]) {
    margin-left: 1.5rem;
}

.details-sample-04 details .summary-icon {
	display: flex;
	height: 1.5rem;
	flex-shrink: 0;
	align-items: center;
	color: rgb(75 85 99 / 1);
}

.details-sample-04 details .summary-icon .open-icon {
    display: block;
    height: 1.5rem;
    width: 1.5rem;
}

.details-sample-04 details .summary-icon .close-icon {
    display: none;
    height: 1.5rem;
    width: 1.5rem;
}

.details-sample-04 details[open] .summary-icon .open-icon {
    display: none;
}

.details-sample-04 details[open] .summary-icon .close-icon {
    display: block;
}

.details-sample-04 details .details-text {
	padding-bottom: 1.5rem;
	color: rgb(55 65 81 / 1);
}

.details-sample-04 details .details-text ul {
    padding: 0;
    margin: 0;
	list-style-type: none;
}

.details-sample-04 details .details-text ul li a {
	padding-left: 1.5rem;
	padding-right: 1.5rem;
	padding-top: 0.625rem;
	padding-bottom: 0.625rem;
	text-decoration-line: none;
	transition-property: background-color;
	transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
	transition-duration: 150ms;
}

.details-sample-04 details .details-text ul li a {
	color: rgb(17 24 39 / 1);
	display: flex;
	align-items: center;
	justify-content: space-between;
}

.details-sample-04 details .details-text ul li a:hover {
	background-color: rgb(249 250 251 / 0.8);
}

.details-sample-04 details .details-text ul li svg {
	height: 1rem;
	width: 1.5rem;
	flex-shrink: 0;
}

ソースコード

HTML
<div class="details-sample-05">
    <h2 class="details-sample-header">サンプル 05</h2>
    <div class="details-wrap">
        <!--↓ここからがひとつのブロック↓-->
        <details>
            <summary>
                <span class="summary-text">
                    サービス案内
                </span>
                <span class="summary-icon" aria-hidden="true">
                    <svg class="open-icon" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M12 6v12m6-6H6" />
                    </svg>
                    <svg class="close-icon" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M18 12H6" />
                    </svg>
                </span>
            </summary>
            <!--↓ここからがひとつのサブブロック↓-->
            <details class="sub-details">
                <summary>
                    <span class="summary-text">
                        ウェブサイト制作
                    </span>
                    <span class="summary-icon" aria-hidden="true">
                        <svg class="arrow-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" >
                            <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
                        </svg>
                    </span>
                </summary>
                <div class="details-text">
                    <ul>
                        <li>
                            <a href="#">
                                コンテンツへのリンク
                                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
                                    <path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" />
                                </svg>
                            </a>
                        </li>
                        <li>
                            <a href="#">
                                コンテンツへのリンク
                                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
                                    <path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" />
                                </svg>
                            </a>
                        </li>
                    </ul>
                </div>
            </details>
            <!--↑ここまでがひとつのサブブロック↑-->
        </details>
        <!--↑ここまでがひとつのブロック↑-->
    </div>
</div>
CSS
/*---
下記 CSS はあくまでサンプルです。
他のCSSやブラウザの標準スタイルとの関係で調整が必要かもしれません
---*/

.details-sample-05 {
    margin-left: auto;
    margin-right: auto;
    max-width: 64rem;
}

.details-sample-05 .details-sample-header {
    font-size: 1.5rem;
    font-weight: 700;
    color: rgb(17 24 39 / 1);
}

.details-sample-05 .details-wrap > :not([hidden]) ~ :not([hidden]) {
	border-top-width: 1px;
    border-top-style: solid;
	border-color: rgb(17 24 39 / 0.1);
}

.details-sample-05 .details-wrap {
    margin-top: 2.5rem;
	border-radius: 0.5rem;
    border-style: solid;
	border-width: 1px;
	border-color: rgb(17 24 39 / 0.1);
}

.details-sample-05 details {
    padding: 0;
    margin: 0;
}

.details-sample-05 details summary {
    box-sizing: border-box;
	padding: 1.5rem;
	color: rgb(17 24 39 / 1);
	display: flex;
	width: 100%;
	list-style-type: none;
	align-items: flex-start;
	justify-content: space-between;
}

.details-sample-05 details summary:hover {
    cursor: pointer;
}

.details-sample-05 details summary::-webkit-details-marker {
    display: none;
}

.details-sample-05 details .summary-text {
    width: 100%;
    font-size: 1rem;
    font-weight: 600;
}

.details-sample-05 details summary > :not([hidden]) ~ :not([hidden]) {
    margin-left: 1.5rem;
}

.details-sample-05 details .summary-icon {
	display: flex;
	height: 1.5rem;
	flex-shrink: 0;
	align-items: center;
	color: rgb(75 85 99 / 1);
}

.details-sample-05 details .summary-icon .open-icon {
    display: block;
    height: 1.5rem;
    width: 1.5rem;
}

.details-sample-05 details .summary-icon .close-icon {
    display: none;
    height: 1.5rem;
    width: 1.5rem;
}

.details-sample-05 details[open] .summary-icon .open-icon {
    display: none;
}

.details-sample-05 details[open] .summary-icon .close-icon {
    display: block;
}

.details-sample-05 details.sub-details {
    border-top-width: 1px;
    border-top-style: solid;
	border-color: rgb(17 24 39 / 0.1);
}

.details-sample-05 details.sub-details summary {
	background-color: rgb(249 250 251 / 0.8);
}

.details-sample-05 details.sub-details .summary-icon .arrow-icon {
	height: 1.5rem;
	width: 1.5rem;
	transition-property: transform;
	transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
	transition-duration: 150ms;
}

.details-sample-05 details.sub-details[open] .summary-icon .arrow-icon {
	transform: rotate(180deg);
}

.details-sample-05 details .details-text {
	color: rgb(55 65 81 / 1);
}

.details-sample-05 details .details-text ul {
    padding: 0;
    margin: 0;
	list-style-type: none;
}

.details-sample-05 details .details-text ul li a {
	padding-left: 1.5rem;
	padding-right: 1.5rem;
    padding-top: 0.75rem;
    padding-bottom: 0.75rem;
	text-decoration-line: none;
	transition-property: background-color;
	transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
	transition-duration: 150ms;
}

.details-sample-05 details .details-text ul li a {
	color: rgb(17 24 39 / 1);
	display: flex;
	align-items: center;
	justify-content: space-between;
}

.details-sample-05 details .details-text ul li a:hover {
	background-color: rgb(249 250 251 / 0.8);
}

.details-sample-05 details .details-text ul li svg {
	height: 1rem;
	width: 1.5rem;
	flex-shrink: 0;
}