Plus d'options de style 

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.

Browser Support

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

Source

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

Enregistrement de https://codepen.io/web-dot-dev/pen/VwoBQjY dans Chrome 131

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

Enregistrement de https://codepen.io/web-dot-dev/pen/oNKMEYv dans Chrome 131

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

Enregistrement de https://codepen.io/web-dot-dev/pen/XWvBZNo dans Chrome 131

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

Enregistrement de https://codepen.io/web-dot-dev/pen/ExqpQZM dans Chrome 131

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

Enregistrement de https://codepen.io/web-dot-dev/pen/rNXrJyQ dans Chrome 131

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

Enregistrement de https://codepen.io/web-dot-dev/pen/PoMBQmW dans Chrome 131

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é.