公開日: 2024 年 11 月 6 日
Chrome 131 以降では、<details>
要素と <summary>
要素の構造にスタイルを適用するオプションが追加されました。これらの要素は、開示ウィジェットやアコーディオン ウィジェットを作成する際に使用できます。
特に、Chrome 131 で導入された変更により、これらの要素で display
プロパティを使用できるようになり、::details-content
疑似要素が追加され、展開と閉じを切り替える部分にスタイルを適用できるようになりました。
対応ブラウザ
<details>
要素に display
を設定する
これまで、<details>
要素の表示タイプを変更することはできませんでした。この制限は緩和され、<details>
要素でグリッド レイアウトや Flex レイアウトを使用できるようになりました。
次の例の排他的アコーディオンは、複数の <details>
要素が並べて配置されています。いずれかの <details>
要素を開くと、そのコンテンツが <summary>
の横に配置されます。
デモ
記録中
これは、次の CSS を使用して <details>
要素に Flex レイアウトを使用すると実現できます。
details {
display: flex;
flex-direction: row;
}
grid
など、他の表示値も使用できます。
display: inline
の使用に関する注意事項
予期しない結果を招く可能性がある display
値は inline
です。機能しないわけではなく、HTML パーサーの制限が原因です。
<details>
要素を段落内に配置すると、HTML 標準のセクション 13.2.6.4.7 で定義されているように、HTML パーサーは開いている段落を最初に閉じます。
タグ名が「address」、「article」、「aside」、「blockquote」、「center」、「details」、「dialog」、「dir」、「div」、「dl」、「fieldset」、「figcaption」、「figure」、「footer」、「header」、「hgroup」、「main」、「menu」、「nav」、「ol」、「p」、「search」、「section」、「summary」、「ul」のいずれかである開始タグ
開いている要素のスタックにボタンスコープ内の p 要素がある場合は、p 要素を閉じます。トークンの HTML 要素を挿入します。
その結果、display: inline
が設定されているかどうかにかかわらず、<details>
はブロック方向に流れます。
たとえば、次のマークアップ
<p>Hello <details>…</details> world</p>
解析後は次のようになります。
<p>Hello </p><details>…</details> world<p></p>
こちらのデモで、Chrome DevTools を使用して解析されたマークアップを調べて確認できます。
これは、<p>
内に <details>
をネストする場合にのみ適用されます。<div>
内の <details>
で display: inline
を使用すると、正常に動作します。
::details-content
疑似
ブラウザでは、<details>
要素は Shadow DOM を使用して実装されます。概要(デフォルトの概要の子要素を含む)に 1 つの <slot>
が含まれ、残りのすべてのコンテンツ(<summary>
要素を除く <details>
要素のすべての子)に 1 つの <slot>
が含まれます。
<details>
↳ #shadow-root (user-agent)
<slot id="details-summary">
<summary>Details</summary>
<!-- The summary goes here -->
</slot>
<slot id="details-content">
<!-- All content goes here -->
</slot>
</details>
<details>
でより多くの表示タイプを使用できるだけでなく、::details-content
疑似要素を使用してコンテンツ スロットをターゲットに設定できるようになりました。この疑似要素を使用すると、<details>
要素のコンテンツをラップするコンテナのスタイルを設定できます。
details::details-content {
border: 5px dashed hotpink;
}
<details>
要素が開いた状態の場合にのみ、設定したスタイルを適用するには、その前に [open]
セレクタを追加します。
[open]::details-content {
border: 5px dashed hotpink;
}
<details>
要素が [open]
状態にある場合にのみ、::details-content
疑似要素にスタイルを適用することをおすすめします。
デモ
記録中
::details-content
の display
タイプは UA スタイルシートで block
に設定されていますが、以前は display: contents
でした。この変更は、height: 100%
に依存する開示済みコンテンツなど、場合によっては不利に働く可能性があります。これが問題である場合は、display
の型を contents
に戻すことで回避できます(例: details[open]::details-content { display: contents; }
)。
::details-content
疑似要素をアニメーション化する
<details>
要素のコンテンツは、展開時にアニメーション化できます。次の例では、幅が 0px
から 300px
にアニメーション化されます。
::details-content {
transition: width 0.5s ease, content-visibility 0.5s ease allow-discrete;
width: 0;
}
[open]::details-content {
width: 300px;
}
width
の遷移に加えて、content-visibility
プロパティも遷移する必要があります。これは、User-Agent スタイルシートで定義されているように、この値が未開状態と開いた状態の間で変化するためです。このプロパティは個別にアニメーション化できるプロパティであるため、動作させるには allow-discrete
キーワードが必要です。
前に共有した限定公開のアコーディオン デモに追加すると、次のような結果になります。
デモ
記録中
height
はアニメーション化することもできます。height: auto
にアニメーション化するには、interpolate-size
または calc-size()
を使用する必要があります。また、::details-content
疑似からコンテンツが流出しないように、overflow: clip
を適用します。
::details-content {
transition: height 0.5s ease, content-visibility 0.5s ease allow-discrete;
height: 0;
overflow: clip;
}
/* Browser supports interpolate-size */
@supports (interpolate-size: allow-keywords) {
:root {
interpolate-size: allow-keywords;
}
[open]::details-content {
height: auto;
}
}
/* Fallback for browsers with no interpolate-size support */
@supports not (interpolate-size: allow-keywords) {
[open]::details-content {
height: 150px;
overflow-y: scroll; /* In case the contents should be taller than 150px */
}
}
コードの動作は、マテリアル UI のアコーディオンにインスパイアされた次のデモで確認できます。各 <details>
要素の内容が適切にアニメーション化されます。
デモ
記録中
::details-content
をサポートしていないブラウザでも、コンポーネントは正常に動作します。訪問者に表示されるのはアニメーションのみです。
特徴検出
CSS の ::details-content
疑似クラスのサポートを機能検出するには、次のスニペットを使用します。
@supports selector(::details-content) {
…
}
また、この検出結果をヒントとして、訪問者が使用しているブラウザが追加の表示値をサポートしているかどうかを判断することもできます。
ユーザー補助に関する考慮事項
::details-content
疑似要素の導入と表示タイプの変更は、<details>
要素のユーザー補助には影響しません。
少なくとも Chromium ベースのブラウザと HTML 標準では、以前と同様に、<details>
要素は検索可能であり、ブラウザがページ内検索、ScrollToTextFragment、要素フラグメント ナビゲーションに応じて非表示のコンテンツにスクロールしようとすると自動的に展開されます。これは変更されません。
ただし、排他的アコーディオンを使用する前に、それがユーザーにとって有用かどうか、有害かどうかを検討してください。排他的アコーディオンを使用すると、コンテンツが占有する視覚的なスペースの量は減りますが、ユーザーがすべての情報を確認するには、多くのアイテムを開く必要がある場合があります。複数の商品を同時に見たいユーザーにとっては不便です。
マーカーのスタイル設定はどうすればよいですか?
現在、リストマーカーのスタイル設定は相互運用できません。Gecko と(現在の)Chromium で採用されているアプローチと、WebKit(以前は Chromium と共有されていた)で採用されているアプローチの 2 つの異なるアプローチがあるためです。
この機能が相互運用可能になれば、マーカーのスタイル設定をより細かく制御できるようになります。
その他のデモ
最後に、デモをいくつかご紹介します。これらはすべて ::details-content
を使用します。
UIKit アコーディオン
デモ
記録中
このデモは UIKit アコーディオンをベースに作成されています。コードは、前に共有したマテリアル UI のアコーディオンとほぼ同じです。
開いている開示ウィジェット
デモ
記録中
このデモでは、コンテンツがすでに画面に表示されている、開いている開示ウィジェットが部分的に表示されています。これを実現するため、content-visibility
は常に visible
に設定されます。計算が伴うため、height
は calc-size()
を使用してアニメーション化されます。
::details-content {
content-visibility: visible; /* Make it always visible */
transition: height 0.5s ease;
height: 150px;
overflow: clip;
}
[open]::details-content {
height: calc-size(auto, size + 0.5rem); /* calc-size because we need to add a length */
}
スタイル設定を簡単にするため、コンテンツはラッパー div でラップされています。ラッパー div には padding
などのレイアウト スタイルが適用され、::details-content
疑似要素がアニメーション化されます。