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 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 ajoutent un pseudo-élément ::details-content pour styliser la partie qui se développe et se réduit.

Navigateurs pris en charge

  • Chrome: 131.
  • Edge: 131.
  • Firefox: non compatible.
  • Safari: non compatible.

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 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 l'élément <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 flex sur l'élément <details>, à l'aide du code CSS suivant:

details {
  display: flex;
  flex-direction: row;
}

D'autres valeurs d'affichage, telles que grid, sont également autorisées.

Remarque concernant l'utilisation de display: inline

La valeur inline peut entraîner un résultat inattendu.display 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 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> dans un <div> fonctionne parfaitement.

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

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 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 change entre les états "non ouvert" et "ouvert", comme 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

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

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 voir 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> est animé de manière agréable.

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 voient pas est l'animation.

Détection de fonctionnalités

Pour détecter la prise en charge du pseudo ::details-content en CSS, utilisez l'extrait de code 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 auparavant, au moins dans les navigateurs basés sur Chromium et conformément à la norme HTML, l'élément <details> est accessible par recherche et se développe automatiquement lorsque le navigateur tente de faire défiler son contenu masqué en réponse à la recherche dans la page, à ScrollToTextFragment et à la navigation dans les fragments d'éléments. 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 souhaitent consulter plusieurs articles 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.

Autres démonstrations

Pour terminer, voici quelques autres démonstrations à 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émonstration est créée après 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

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

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