スタイル設定のその他のオプション(<詳細>)

公開日: 2024 年 11 月 6 日

Chrome 131 以降では、<details> 要素と <summary> 要素の構造のスタイル設定を行うためのオプションが増えました。これらの要素は、開示ウィジェットやアコーディオン ウィジェットを作成する際に使用できます。

具体的には、Chrome 131 で導入された変更により、これらの要素で display プロパティを使用できるようになり、展開と折りたたみの部分にスタイルを設定する ::details-content 疑似要素が追加されました。

Browser Support

  • Chrome: 131.
  • Edge: 131.
  • Firefox: 143.
  • Safari: 18.4.

Source

<details> 要素に display を設定する

これまで、<details> 要素の表示タイプを変更することはできませんでした。この制限が緩和され、たとえば <details> 要素でグリッド レイアウトやフレックス レイアウトを使用できるようになりました。

次の例では、排他的アコーディオンは、横に並べられた複数の <details> 要素で構成されています。<details> 要素の 1 つを展開すると、そのコンテンツが <summary> の横に配置されます。

デモ

録画中

Chrome 131 での https://codepen.io/web-dot-dev/pen/VwoBQjY の録画

これは、次の CSS を使用して <details> 要素にフレックス レイアウトを使用することで実現されます。

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 を使用して実装されます。概要用の <slot>(デフォルトの概要子を含む)と、残りのすべてのコンテンツ用の <slot><summary> 要素を除く <details> 要素のすべての子)が含まれます。

<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 疑似クラスにスタイルを適用することをおすすめします。

デモ

録画中

Chrome 131 での https://codepen.io/web-dot-dev/pen/oNKMEYv の録画

::details-contentdisplay 型は 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 キーワードが必要です。

前に共有した排他的アコーディオンのデモに追加すると、次のようになります。

デモ

録画中

Chrome 131 での https://codepen.io/web-dot-dev/pen/XWvBZNo の録画

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 */
    }
}

次のデモ(Material UI のアコーディオンにインスピレーションを得たもの)で、コードの動作を確認できます。各 <details> 要素の内容がスムーズにアニメーション表示されます。

デモ

録画中

Chrome 131 での https://codepen.io/web-dot-dev/pen/ExqpQZM の録画

::details-content をサポートしていないブラウザでも、コンポーネントは正常に動作します。アニメーションは表示されません。

特徴検出

CSS で ::details-content 疑似クラスのサポートを検出するには、次のスニペットを使用します。

@supports selector(::details-content) {
  
}

この検出を、サイト訪問者が使用しているブラウザが追加の表示値をサポートしているかどうかを判断するためのチェックとして使用することもできます。

ユーザー補助に関する考慮事項

::details-content 疑似要素の導入と表示タイプの変更機能は、<details> 要素のアクセシビリティに影響しません。

以前と同様に、少なくとも Chromium ベースのブラウザと HTML 標準では、<details> 要素は検索可能であり、ブラウザがページ内検索、ScrollToTextFragment、要素フラグメント ナビゲーションに応じて非表示のコンテンツにスクロールしようとすると、自動的に展開されます。これは変更されません。

ただし、排他的アコーディオンを使用する前に、ユーザーにとって有益か有害かを検討してください。排他的なアコーディオンを使用すると、コンテンツが占める視覚的なスペースは減りますが、ユーザーはすべての情報を確認するために多くの項目を開く必要が生じる可能性があります。複数のアイテムを同時に確認したいユーザーにとっては不便です。

マーカーのスタイル設定はどうすればよいですか?

現在、リストマーカーのスタイル設定は相互運用できません。Gecko と(現在の)Chromium で採用されているアプローチと、WebKit で採用されているアプローチ(以前は Chromium と共有)の 2 つがあるためです。

相互運用が可能になったら、マーカーのスタイル設定をより細かく制御できるようにする予定です。

その他のデモ

最後に、その他のデモをいくつかご紹介します。これらはすべて ::details-content を使用します。

UIKit アコーディオン

デモ

録画中

Chrome 131 での https://codepen.io/web-dot-dev/pen/rNXrJyQ の録画

このデモは UIKit アコーディオンをベースにしています。コードは、以前に共有した Material UI アコーディオンとほぼ同じです。

一部開いた開示ウィジェット

デモ

録画中

Chrome 131 での https://codepen.io/web-dot-dev/pen/PoMBQmW の録画

このデモでは、コンテンツがすでに画面に表示されている開いた状態の開示ウィジェットが使用されています。このため、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 疑似要素がアニメーション化されます。