これは知っておくとかなり便利! details要素にname属性を与えると、連動して開閉するアコーディオンを実装できます
Post on:2024年1月11日
<details>
要素でアコーディオンを簡単に実装できますが、懸念点は複数のウィジェットが個別に開閉してしまうことです。1つ目を開いて、2つ目を開くと、1つ目は開いたままです。1つ目を閉じるには、1つ目をクリックして閉じる必要がありました。
しかし、<details>
要素にname
属性を与えると、すべてのウィジェットを連動して開閉させることができます。1つのウィジェットだけを開くことができる排他的アコーディオンをHTMLとCSSだけで実装する方法を紹介します。
Exclusive Accordion
by Bramus
下記は各ポイントを意訳したものです。
※元サイト様のライセンスに基づいて翻訳しています。基づいてというのは、貢献部分に関して同ライセンスも含みます。
アコーディオンの実装
Webページでよく使用されるUIパターンの一つに、アコーディオンのコンポーネントがあります。アコーディオンとは、個別にコンテンツを表示(または非表示)するために展開(または折りたたみ)できる複数のウィジェットで構成されるコンポーネントです。
アコーディオンを実装するには、<details>
要素をいくつか組み合わせ、それらが同じコンポーネントであることを示すためにグループ化します。
下記のデモは、HTMLとCSSで実装したアコーディオンのコンポーネントです。
1, 2, 3, 4のをクリックすると、各コンテンツが表示されます。4つのウィジェットの展開(または折りたたみ)は独立しており、全部を表示することもできます。
See the Pen
Exclusive Accordion Demo 1/3: Accordion by coliss (@coliss)
on CodePen.
1つのウィジェットだけを開くことができる排他的アコーディオン
アコーディオンのバリエーションとして、1つのウィジェットだけを開くことができる排他的アコーディオン(The exclusive accordion)があります。
これは<details>
要素でname
属性が使用できるようになったからです。サポートブラウザは、Chrome 120, Edge 120, Safari 17.2です。
参考: <details> name attribute
実装は簡単で、<details>
要素にname
属性を与えます。同じname
属性を持つ複数の<details>
要素はセマンティックなグループを形成し、排他的アコーディオンとして振る舞います。つまり、<details>
要素の1つを展開すると、他の展開していた要素は自動的に折りたたみます。
1 2 3 4 5 6 7 8 9 10 11 12 |
<details name="learn-css"> <summary>Welcome to Learn CSS!</summary> <p>…</p> </details> <details name="learn-css"> <summary>Box Model</summary> <p>…</p> </details> <details name="learn-css"> <summary>Selectors</summary> <p>…</p> </details> |
実際の動作は、デモページでご覧ください。
1, 2, 3, 4のをクリックすると、各コンテンツが表示されます。4つのウィジェットの展開(または折りたたみ)は連動しており、1つを表示すると他は非表示になります。
See the Pen
Exclusive Accordion Demo 2/3: Exclusive Accordion by coliss (@coliss)
on CodePen.
この排他的アコーディオンは、ページ上に複数実装することができます。
<details>
要素に新しいname
属性を与えるたびに、新しい論理グループが形成されます。
See the Pen
Exclusive Accordion Demo 3/3: Exclusive Accordion by coliss (@coliss)
on CodePen.
排他的アコーディオンの一部である<details>
要素は、必ずしも兄弟である必要はないことに注目してください。ドキュメント内に散在していても構いません。それらの<details>
要素をグループ化するのはDOMの順序ではなく、name
属性です。
排他的アコーディオンのポリフィル
下記のJavaScriptを使用すると、排他的アコーディオンの動作をポリフィルすることができます。コードは<details>
要素のtoggle
イベントに依存しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
document.querySelectorAll("details[name]").forEach(($details) => { $details.addEventListener("toggle", (e) => { const name = $details.getAttribute("name"); if (e.newState == "open") { document .querySelectorAll(`details[name=${name}][open]`) .forEach(($openDetails) => { if (!($openDetails === $details)) { $openDetails.removeAttribute("open"); } }); } }); }); |
あるname
を持つ<details>
要素が開くと、name
属性に同じ値を持つ他の<details>
要素を見つけて閉じます。
古いバージョンの一部のブラウザでは、このtoggle
イベントが発生しません。それらのブラウザでは、このポリフィルのコードは何もしません。プログレッシブエンハンスメントの観点から、これは許容できる動作です。
sponsors