Accordion
ネイティブの details 要素を基本とするアコーディオン。高さをアニメーションしたい場合は、JavaScript で制御する構造も選べます。
<pe-accordion class="Accordion">
<details class="Item" data-accordion-item data-accordion-value="shipping" name="faq">
<summary class="Trigger">How long does shipping take?</summary>
<p class="Content">Standard shipping arrives within three to five business days.</p>
</details>
<details class="Item" data-accordion-item data-accordion-value="returns" name="faq">
<summary class="Trigger">Can I return an item?</summary>
<p class="Content">Unused items can be returned within 30 days.</p>
</details>
</pe-accordion>.Accordion {
display: flex;
max-width: 20rem;
width: 100%;
flex-direction: column;
border: 1px solid oklch(14.5% 0 0);
color: oklch(14.5% 0 0);
@media (prefers-color-scheme: dark) {
border-color: white;
color: white;
}
}
.Accordion .Item + .Item {
border-top: 1px solid oklch(14.5% 0 0);
@media (prefers-color-scheme: dark) {
border-top-color: white;
}
}
.Accordion .Trigger {
padding: 0.5rem 0.75rem;
cursor: pointer;
}
.Accordion .Content {
margin: 0;
padding: 0 0.75rem 0.75rem;
}
Accordion は、関連する複数の開閉項目をグループとして扱うときに使います。基本はネイティブの <details> / <summary> を使います。同時に 1 つだけ開くには各 <details> に同じ name を指定し、複数開く場合は省略します。対応ブラウザでは ::details-content でアニメーションできます。
高さをアニメーションする制御方式
Section titled “高さをアニメーションする制御方式”計測した高さのアニメーションや独自のトリガー/パネル構造が必要な場合だけ、制御方式を使います。
<pe-accordion class="Accordion" data-accordion-single data-accordion-hidden-until-found> <div class="Item" data-accordion-item data-accordion-value="shipping"> <h3 class="Header"> <button type="button" class="Trigger" data-accordion-trigger>Shipping</button> </h3> <div class="Panel" data-accordion-panel> <div class="Content">Shipping information.</div> </div> </div></pe-accordion>1 つのホスト内で方式を混在させないでください。閉じた内容をページ内検索の対象にする場合は data-accordion-hidden-until-found を追加します。
<pe-accordion class="Accordion" data-accordion-single data-accordion-hidden-until-found>
<div class="Item" data-accordion-item data-accordion-value="shipping">
<h3 class="Header">
<button type="button" class="Trigger" data-accordion-trigger>Shipping</button>
</h3>
<div class="Panel" data-accordion-panel>
<div class="Content">Shipping information.</div>
</div>
</div>
</pe-accordion>.Accordion {
display: flex;
max-width: 20rem;
width: 100%;
flex-direction: column;
border: 1px solid oklch(14.5% 0 0);
color: oklch(14.5% 0 0);
@media (prefers-color-scheme: dark) {
border-color: white;
color: white;
}
}
.Accordion .Item + .Item {
border-top: 1px solid oklch(14.5% 0 0);
@media (prefers-color-scheme: dark) {
border-top-color: white;
}
}
.Accordion .Header {
margin: 0;
}
.Accordion .Trigger {
display: flex;
width: 100%;
align-items: center;
justify-content: space-between;
gap: 1rem;
padding: 0.5rem 0.75rem;
margin: 0;
border: none;
border-radius: 0;
background-color: transparent;
color: inherit;
font-family: inherit;
font-size: 0.875rem;
font-weight: 400;
line-height: 1.25rem;
text-align: left;
cursor: pointer;
@media (hover: hover) {
&:hover:not([data-disabled]) {
background-color: oklch(97% 0 0);
@media (prefers-color-scheme: dark) {
background-color: oklch(26.9% 0 0);
}
}
}
&::after {
content: "+";
}
&[data-state="open"]::after {
content: "−";
}
}
.Accordion .Panel {
height: var(--accordion-panel-height);
overflow: hidden;
font-size: 0.875rem;
line-height: 1.25rem;
transition: height 150ms ease-out;
&[data-starting-style],
&[data-ending-style] {
height: 0;
}
}
.Accordion .Content {
padding: 0 0.75rem 0.75rem;
}
@media (prefers-reduced-motion: reduce) {
.Accordion .Panel {
transition-duration: 0s;
}
}
| パーツ | ネイティブ方式 | 制御方式 |
|---|---|---|
| ホスト | <pe-accordion> |
<pe-accordion> |
| 項目 | details[data-accordion-item] |
div[data-accordion-item] |
| トリガー | 直下の <summary> |
<button data-accordion-trigger> |
| パネル | <summary> 以外の内容 |
[data-accordion-panel] |
| 開閉状態 | 項目の open |
項目の data-accordion-open |
| 値 | 項目の data-accordion-value |
項目の data-accordion-value |
制御方式は初期状態で複数項目を開けます。1 つに制限する場合は data-accordion-single を指定します。すべてのパーツは data-state="open|closed" を公開します。
API リファレンス
Section titled “API リファレンス”制御方式の属性
Section titled “制御方式の属性”| 名前 | 説明 |
|---|---|
data-accordion-open | 制御方式の項目に現在の開閉状態を反映します。外部から変更することもできます。 |
data-accordion-single | 制御方式のホストに指定すると、同時に開ける項目を 1 つに制限します。 |
data-accordion-hidden-until-found | 制御方式のホストまたはパネルに指定すると、閉じている間は hidden="until-found" を使い、beforematch イベントですぐに開きます。 |
ホストメソッド
Section titled “ホストメソッド”| 名前 | 型 | 説明 |
|---|---|---|
open(valueOrItem) | void | data-accordion-value または details/div 要素参照でアイテムを開きます。 |
close(valueOrItem) | void | 値または要素参照でアイテムを閉じます。 |
toggle(valueOrItem) | void | 値または要素参照でアイテムを切り替えます。 |
ホストの value プロパティでは、開いている項目の data-accordion-value を配列で取得・設定できます。disabled プロパティは、ホストの data-accordion-disabled と同期します。複数の値を設定した場合に同時に開けるかどうかは、ネイティブ方式では details[name]、制御方式では data-accordion-single によって決まります。
ホストプロパティ
Section titled “ホストプロパティ”| 名前 | 型 | 説明 |
|---|---|---|
value | string[] | `data-accordion-value` から開いているアイテム値を取得または設定します。 |
disabled | boolean | `data-accordion-disabled` 経由でルート無効状態を取得または設定します。 |
アイテム属性
Section titled “アイテム属性”| 名前 | 説明 |
|---|---|
data-accordion-item | ネイティブ方式の `<details>` または制御方式の `<div>` を、アコーディオンの項目として指定します。 |
data-accordion-value | open()、close()、toggle() で項目を指定するための文字列です。 |
data-accordion-open | 制御方式の項目に、初期状態または現在の開閉状態を設定します。 |
data-accordion-disabled | ホストまたは項目に指定すると、利用者による開閉操作を無効にします。 |
data-state | アイテム、トリガー、パネル上: "open" または "closed"。 |
data-index | ホスト内のゼロ始まりアイテムインデックス。 |
data-disabled | ルート無効時のホスト上: 空属性として存在します。 |
| 名前 | 説明 |
|---|---|
pe-accordion:open | 項目が開いたときに発火します。イベントはバブリングし、Shadow DOM の境界も越えます。 |
pe-accordion:close | 項目が閉じたときに発火します。イベントはバブリングし、Shadow DOM の境界も越えます。 |
イベントの detail には、item、trigger、summary(trigger と同じ値)、panel(ネイティブ方式では null)、任意の value、index、reason が含まれます。reason は trigger、programmatic、attribute、beforematch、native のいずれかです。各 <details> では、ネイティブの toggle イベントも利用できます。
制御方式のアニメーション
Section titled “制御方式のアニメーション”開閉アニメーション中は、制御方式のパネルの高さと幅を --accordion-panel-height、--accordion-panel-width で参照できます。
.Panel { height: var(--accordion-panel-height); overflow: hidden; transition: height 160ms ease;}
.Panel[data-starting-style],.Panel[data-ending-style] { height: 0;}時間が有限の非表示アニメーション終了後にパネルを隠します。beforematch ではすぐにスクロールできるよう表示アニメーションを省略します。