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 d'affichage ou d'accordéon.
Plus précisément, les modifications introduites dans Chrome 131 permettent d'utiliser la propriété display
sur ces éléments et d'ajouter un pseudo-élément ::details-content
pour styliser la partie qui se développe et se réduit.
Navigateurs pris en charge
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 en flex sur l'élément <details>
.
Dans l'exemple suivant, l'accordéon exclusif est constitué 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 au niveau de l'élément <details>
avec le code CSS suivant:
details {
display: flex;
flex-direction: row;
}
D'autres valeurs d'affichage, telles que grid
, sont également autorisées.
Remarque sur l'utilisation de display: inline
La valeur inline
peut entraîner 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 :
Balise de début dont le nom est l'un des suivants : "address", "article", "aside", "citation", "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 contient un élément p dans le champ d'application du bouton, fermez un élément p. Insérez un élément HTML pour le jeton.
Par conséquent, <details>
s'écoule dans la direction du bloc, que vous ayez défini display: inline
ou non.
Par exemple, le balisage suivant :
<p>Hello <details>…</details> world</p>
Devient ceci après l'analyse:
<p>Hello </p><details>…</details> world<p></p>
Vous pouvez le constater par vous-même dans cette démonstration 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 bien.
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>
, vous pouvez désormais cibler l'emplacement de contenu à 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 appliquer le style défini uniquement lorsque l'élément <details>
est ouvert, ajoutez-lui le sélecteur [open]
.
[open]::details-content {
border: 5px dashed hotpink;
}
Il est recommandé de n'appliquer un style au pseudo ::details-content
que lorsque l'élément <details>
est dans 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 display: contents
. Dans certains cas, cette modification peut vous nuire, par exemple si le contenu divulgué repose sur height: 100%
. Si cela vous pose problème, vous pouvez contourner ce problème 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 modifiée. En effet, sa valeur passe de l'état non ouvert à l'état ouvert, tel que défini dans la feuille de style user-agent. Étant donné qu'il s'agit d'une propriété pouvant être animée de manière discrète, vous avez besoin du mot clé allow-discrete
pour qu'elle fonctionne.
Ajouté à la démo exclusive de l'accordéon partagée précédemment, le résultat est le suivant:
Démo
Enregistrement
height
peut également être animé. Pour animer vers height: auto
, vous devez utiliser interpolate-size
ou calc-size()
. De plus, pour éviter que le contenu ne dépasse le 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 observer le code en action dans la démonstration suivante, inspirée de l'accordéon de Material UI. Le contenu de chaque élément <details>
s'anime correctement.
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 voient pas est l'animation.
Détection de fonctionnalités
Pour détecter la compatibilité avec le pseudo ::details-content
en CSS, utilisez l'extrait suivant.
@supports selector(::details-content) {
…
}
Vous pouvez également utiliser cette détection comme vérification pour déterminer si le navigateur utilisé par votre visiteur est compatible avec les valeurs d'affichage supplémentaires ou non.
Considérations sur l'accessibilité
L'introduction du pseudo-élément ::details-content
et la possibilité de modifier le type d'affichage n'ont aucune incidence sur l'accessibilité de l'élément <details>
.
Comme précédemment, au moins dans les navigateurs basés sur Chromium et conformément à la norme HTML, l'élément <details>
est inclus dans l'index de recherche et se développe automatiquement lorsque le navigateur tente de faire défiler son contenu caché en réponse à un élément de recherche sur la page, de défilement ToTextFragment et de navigation par fragment d'élément. Cela ne change pas.
Toutefois, avant d'utiliser des accordéons exclusifs, réfléchissez à leur utilité ou à leur nocivité pour les utilisateurs. Bien que l'utilisation d'un accordéon exclusif réduise la quantité d'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 veulent consulter plusieurs éléments en même temps.
Comment définir le style du repère ?
Actuellement, le style du repère 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, nous vous proposerons de mieux contrôler le style du repère.
Plus de démonstrations
Pour terminer, voici quelques autres démonstrations à découvrir. Ils utilisent tous ::details-content
.
Accordéon UIKit
Démo
Enregistrement
Cette démonstration est basée sur l'accordéon UIKit. Le code est pratiquement identique à celui de l'accordéon Material UI partagé précédemment.
Widget de divulgation partiellement ouvert
Démo
Enregistrement
Cette démonstration présente un widget d'informations 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 le style, le contenu est encapsulé dans une div de wrapper. Les styles de mise en page tels que padding
sont appliqués à la div de wrapper, et le pseudo ::details-content
est animé.