Publié le 6 novembre 2024
À partir de Chrome 131, vous disposez de plus d'options pour styliser la structure des éléments <details>
et <summary>
. Vous pouvez désormais utiliser ces éléments lorsque vous créez des widgets de divulgation ou des widgets accordéon.
Plus précisément, les modifications introduites dans Chrome 131 permettent d'utiliser la propriété display
sur ces éléments et ajoutent un pseudo-élément ::details-content
pour styliser la partie qui se développe et se réduit.
Définir display
sur l'élément <details>
Auparavant, il n'était pas possible de modifier le type d'affichage de l'élément <details>
. Cette restriction a été assouplie, ce qui vous permet, par exemple, d'utiliser des mises en page en grille ou Flex sur l'élément <details>
.
Dans l'exemple suivant, l'accordéon exclusif se compose de plusieurs éléments <details>
placés côte à côte. Lorsque vous développez l'un des éléments <details>
, son contenu est placé à côté de <summary>
.
Démo
Enregistrement
Pour ce faire, utilisez une mise en page flexible sur l'élément <details>
, à l'aide du code CSS suivant :
details {
display: flex;
flex-direction: row;
}
D'autres valeurs d'affichage sont également autorisées, comme grid
.
Remarque sur l'utilisation de display: inline
inline
est une valeur display
qui peut avoir un résultat inattendu. Non pas parce qu'il ne fonctionne pas, mais en raison des limites de l'analyseur HTML.
Lorsque vous placez un élément <details>
dans un paragraphe, l'analyseur HTML est forcé de fermer d'abord le paragraphe ouvert, comme défini dans la section 13.2.6.4.7 de la norme HTML :
Une balise de début dont le nom est l'un des suivants : "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"
Si la pile d'éléments ouverts comporte un élément p dans la portée du bouton, fermez un élément p. Insérez un élément HTML pour le jeton.
Par conséquent, le flux <details>
s'écoule dans le sens du bloc, même si vous avez défini display: inline
.
Par exemple, le balisage suivant
<p>Hello <details>…</details> world</p>
Après l'analyse, il devient :
<p>Hello </p><details>…</details> world<p></p>
Vous pouvez le constater par vous-même dans cette démo en inspectant le balisage analysé à l'aide des outils pour les développeurs Chrome.
Notez que cela ne s'applique qu'à l'imbrication de <details>
dans un <p>
. L'utilisation de display: inline
sur un <details>
à l'intérieur d'un <div>
fonctionne correctement.
Le pseudo ::details-content
Dans les navigateurs, l'élément <details>
est implémenté à l'aide de Shadow DOM. Il contient un <slot>
pour le résumé (avec un enfant de résumé par défaut) et un <slot>
pour tout le contenu restant, c'est-à-dire tous les enfants de l'élément <details>
, à l'exception de l'élément <summary>
.
<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>
En plus d'utiliser davantage de types d'affichage sur <details>
, l'emplacement de contenu peut désormais être ciblé à l'aide du pseudo-élément ::details-content
. Vous pouvez utiliser ce pseudo pour styliser le conteneur qui encapsule le contenu de l'élément <details>
.
details::details-content {
border: 5px dashed hotpink;
}
Pour n'appliquer le style défini que lorsque l'élément <details>
est ouvert, ajoutez-lui le sélecteur [open]
.
[open]::details-content {
border: 5px dashed hotpink;
}
Nous vous recommandons de n'appliquer un style au pseudo-élément ::details-content
que lorsque l'élément <details>
est à l'état [open]
.
Démo
Enregistrement
Le type display
de ::details-content
est défini sur block
dans la feuille de style UA, alors qu'il était auparavant défini sur display: contents
. Cette modification peut vous être défavorable dans certains cas, par exemple si le contenu divulgué repose sur height: 100%
. Si cela vous pose problème, vous pouvez le contourner en rétablissant le type display
sur contents
, comme suit : details[open]::details-content { display: contents; }
.
Animer le pseudo ::details-content
Vous pouvez animer le contenu de l'élément <details>
lorsqu'il se développe. Dans l'exemple suivant, la largeur passe de 0px
à 300px
.
::details-content {
transition: width 0.5s ease, content-visibility 0.5s ease allow-discrete;
width: 0;
}
[open]::details-content {
width: 300px;
}
En plus de la transition de width
, la propriété content-visibility
doit également être migrée. En effet, sa valeur change entre l'état non ouvert et l'état ouvert, comme défini dans la feuille de style User-Agent. Comme il s'agit d'une propriété animable discrète, vous avez besoin du mot clé allow-discrete
pour qu'elle fonctionne.
Si l'on ajoute le résultat à la démo d'accordéon exclusif partagée précédemment, on obtient ceci :
Démo
Enregistrement
Le height
peut également être animé. Pour animer vers height: auto
, vous devez utiliser interpolate-size
ou calc-size()
. De plus, pour empêcher le contenu de déborder du pseudo ::details-content
, appliquez-lui 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 */
}
}
Vous pouvez voir le code en action dans la démo suivante, inspirée de l'accordéon de Material UI. Le contenu de chaque élément <details>
est animé de manière fluide.
Démo
Enregistrement
Dans les navigateurs qui ne sont pas compatibles avec ::details-content
, le composant fonctionne toujours correctement. La seule chose que les visiteurs ne peuvent pas voir, c'est l'animation.
Détection des fonctionnalités
Pour détecter la compatibilité avec la pseudo-classe ::details-content
dans CSS, utilisez l'extrait de code suivant.
@supports selector(::details-content) {
…
}
Vous pouvez également utiliser cette détection comme un indicateur pour déterminer si le navigateur utilisé par votre visiteur est compatible ou non avec les valeurs d'affichage supplémentaires.
Considérations sur l'accessibilité
L'introduction du pseudo-élément ::details-content
et la possibilité de modifier le type d'affichage n'ont aucun impact sur l'accessibilité de l'élément <details>
.
Comme auparavant, au moins dans les navigateurs basés sur Chromium et conformément à la norme HTML, l'élément <details>
est consultable et se développe automatiquement lorsque le navigateur tente de faire défiler son contenu masqué en réponse à la navigation par recherche sur la page, par fragment de texte et par fragment d'élément. Cela ne change pas.
Toutefois, avant d'utiliser des accordéons exclusifs, réfléchissez à leur utilité ou à leur caractère nuisible pour les utilisateurs. Bien que l'utilisation d'un accordéon exclusif réduise l'espace visuel occupé par le contenu, les utilisateurs peuvent avoir à ouvrir de nombreux éléments pour consommer toutes les informations. Cela peut frustrer les utilisateurs qui souhaitent consulter plusieurs éléments en même temps.
Qu'en est-il du style du repère ?
Actuellement, la mise en forme du marqueur de liste n'est pas interopérable, car il existe deux approches différentes : l'une adoptée par Gecko et Chromium (actuel), et l'autre par WebKit (qui était auparavant partagée avec Chromium).
Une fois la fonctionnalité interopérable, notre objectif est de vous donner plus de contrôle sur la façon de styliser le repère.
Autres démonstrations
Pour finir, voici quelques démos supplémentaires à découvrir. Ils utilisent tous ::details-content
.
Accordéon UIKit
Démo
Enregistrement
Cette démo est basée sur l'accordéon UIKit. Le code est pratiquement identique à l'accordéon Material UI partagé précédemment.
Widget de divulgation partiellement ouvert
Démo
Enregistrement
Cette démo présente un widget de divulgation partiellement ouvert dont le contenu est déjà visible à l'écran. Pour ce faire, content-visibility
est toujours défini sur visible
. height
est animé à l'aide de calc-size()
, car un calcul est impliqué.
::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 */
}
Pour faciliter la mise en forme, le contenu est encapsulé dans un div d'encapsulation. Les styles de mise en page tels que padding
sont appliqués au div d'encapsulation, et le pseudo-élément ::details-content
est animé.