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

公開日: 2024 年 11 月 6 日

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

特に、Chrome 131 で導入された変更により、これらの要素で display プロパティを使用できるようになり、::details-content 疑似要素が追加され、展開と閉じを切り替える部分にスタイルを適用できるようになりました。

対応ブラウザ

  • Chrome: 131。
  • Edge: サポートされていません。
  • Firefox: サポートされていません。
  • Safari: サポートされていません。

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

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

次の例の排他的アコーディオンは、複数の <details> 要素が並べて配置されています。いずれかの <details> 要素を開くと、そのコンテンツが <summary> の横に配置されます。

デモ

記録中

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

これは、次の 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 疑似要素にスタイルを適用することをおすすめします。

デモ

記録中

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

コードの動作は、マテリアル 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 アコーディオンをベースに作成されています。コードは、前に共有したマテリアル UI のアコーディオンとほぼ同じです。

開いている開示ウィジェット

デモ

記録中

Chrome 131 における https://codepen.io/web-dot-dev/pen/PoMBQmW の録画

このデモでは、コンテンツがすでに画面に表示されている、開いている開示ウィジェットが部分的に表示されています。これを実現するため、content-visibility は常に visible に設定されます。計算が伴うため、heightcalc-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 疑似要素がアニメーション化されます。