Altre opzioni per lo stile di <details>

Data di pubblicazione: 6 novembre 2024

A partire da Chrome 131, hai più opzioni per definire lo stile della struttura degli elementi <details> e <summary>. Ora puoi utilizzare questi elementi per creare widget di disclaimer o a scomparsa.

In particolare, le modifiche introdotte in Chrome 131 consentono l'utilizzo della proprietà display su questi elementi e aggiungono uno pseudo-elemento ::details-content per applicare lo stile alla parte che si espande e si comprime.

Supporto dei browser

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

Impostazione di display sull'elemento <details>

In passato non era possibile modificare il tipo di visualizzazione dell'elemento <details>. Ora questa limitazione è stata allentata, consentendoti, ad esempio, di utilizzare layout a griglia o flessibili nell'elemento <details>.

Nell'esempio seguente, l'accordion esclusivo è costituito da diversi elementi <details> disposti uno accanto all'altro. Quando espandi uno degli elementi <details>, i relativi contenuti vengono posizionati accanto al <summary>.

Demo

Registrazione

Registrazione di https://codepen.io/web-dot-dev/pen/VwoBQjY in Chrome 131

Questo risultato si ottiene utilizzando un layout flessibile nell'elemento <details>, con il seguente CSS:

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

Sono consentiti anche altri valori di visualizzazione, ad esempio grid.

Una nota sull'utilizzo di display: inline

Un valore display che può avere un esito imprevisto è inline. Non perché non funziona, ma a causa delle limitazioni del parser HTML.

Quando inserisci un elemento <details> all'interno di un paragrafo, il parser HTML è costretto a chiudere prima il paragrafo aperto, come definito nella sezione 13.2.6.4.7 dello standard HTML:

Un tag di inizio il cui nome è uno dei seguenti: "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"

Se la pila di elementi aperti contiene un elemento p nell'ambito del pulsante, chiudi un elemento p. Inserisci un elemento HTML per il token.

Di conseguenza, <details> scorre nella direzione del blocco, indipendentemente dall'impostazione di display: inline.

Ad esempio, il seguente markup

<p>Hello <details>…</details> world</p>

Diventa questo dopo l'analisi:

<p>Hello </p><details>…</details> world<p></p>

Puoi verificare di persona in questa demo ispezionando il markup analizzato utilizzando Chrome DevTools.

Tieni presente che questo vale solo per l'annidamento di <details> all'interno di <p>. L'utilizzo di display: inline su un <details> all'interno di un <div> funziona correttamente.

L'elemento pseudo ::details-content

Nei browser, l'elemento <details> viene implementato utilizzando Shadow DOM. Contiene un elemento <slot> per il riepilogo (con un elemento secondario di riepilogo predefinito) e un elemento <slot> per tutti i contenuti rimanenti, ovvero tutti gli elementi secondari dell'elemento <details> tranne l'elemento <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>

Oltre a utilizzare più tipi di visualizzazione su <details>, ora lo slot dei contenuti può essere scelto come target utilizzando l'elemento pseudo ::details-content. Puoi utilizzare questo pseudo per definire lo stile del contenitore che racchiude i contenuti dell'elemento <details>.

details::details-content {
  border: 5px dashed hotpink;
}

Per applicare lo stile impostato solo quando l'elemento <details> è nello stato aperto, anteponi il selettore [open].

[open]::details-content {
  border: 5px dashed hotpink;
}

Ti consigliamo di applicare gli stili allo pseudo ::details-content solo quando l'elemento <details> è nello stato [open].

Demo

Registrazione

Registrazione di https://codepen.io/web-dot-dev/pen/oNKMEYv in Chrome 131

Il tipo display di ::details-content è impostato su block nel foglio di stile UA, mentre in precedenza era display: contents. In alcuni casi, questa modifica potrebbe svantaggiarti, ad esempio per i contenuti divulgati che si basano su height: 100%. Se riscontri un problema, puoi risolverlo impostando nuovamente il tipo display su contents, come segue: details[open]::details-content { display: contents; }.

Animazione dell'elemento pseudo ::details-content

Puoi animare i contenuti dell'elemento <details> man mano che si espande. Nell'esempio seguente, la larghezza viene animata da 0px a 300px.

::details-content {
  transition: width 0.5s ease, content-visibility 0.5s ease allow-discrete;
  width: 0;
}

[open]::details-content {
  width: 300px;
}

Oltre alla transizione di width, è necessaria anche la transizione della proprietà content-visibility. Questo perché il suo valore cambia tra lo stato non aperto e aperto, come definito nello stile dell'agente utente. Poiché questa proprietà è animabile in modo discreto, è necessaria la parola chiave allow-discrete per il suo funzionamento.

Se aggiungi la demo esclusiva dell'elenco a scomparsa condivisa in precedenza, il risultato sarà il seguente:

Demo

Registrazione

Registrazione di https://codepen.io/web-dot-dev/pen/XWvBZNo in Chrome 131

Il simbolo height può anche essere animato. Per animare height: auto, devi utilizzare interpolate-size o calc-size(). Inoltre, per evitare che i contenuti fuoriescano dall'elemento pseudo ::details-content, applica 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 */
    }
}

Puoi vedere il codice in azione nella seguente demo, ispirata all'accordion di Material UI. I contenuti di ogni elemento <details> vengono animati in modo piacevole.

Demo

Registrazione

Registrazione di https://codepen.io/web-dot-dev/pen/ExqpQZM in Chrome 131

Nei browser che non supportano ::details-content, il componente funziona comunque correttamente. L'unica cosa che i visitatori non possono vedere è l'animazione.

Rilevamento di funzionalità

Per rilevare il supporto della funzionalità pseudo ::details-content in CSS, utilizza lo snippet seguente.

@supports selector(::details-content) {
  
}

Puoi anche utilizzare questo rilevamento come controllo per capire se il browser utilizzato dal visitatore supporta o meno i valori di visualizzazione aggiuntivi.

Considerazioni sull'accessibilità

L'introduzione dello pseudo-elemento ::details-content e la possibilità di modificare il tipo di visualizzazione non influiscono sull'accessibilità dell'elemento <details>.

Come in precedenza, almeno nei browser basati su Chromium e in base allo standard HTML, l'elemento <details> è disponibile per la ricerca e si espande automaticamente quando il browser tenta di scorrere fino ai relativi contenuti nascosti in risposta a Trova nella pagina, ScrollToTextFragment e alla navigazione tra i frammenti di elementi. Questo valore non cambia.

Tuttavia, prima di utilizzare le accordion esclusive, valuta se sono utili o dannose per gli utenti. Sebbene l'utilizzo di una visualizzazione a scomparsa esclusiva riduca lo spazio visivo occupato dai contenuti, gli utenti potrebbero dover aprire molti elementi per visualizzare tutte le informazioni. Ciò potrebbe scontentare gli utenti che vogliono esaminare più elementi contemporaneamente.

E per lo stile dell'indicatore?

Al momento lo stile dell'indicatore di elenco non è interoperabile perché esistono due approcci diversi, uno adottato da Gecko e dalla versione attuale di Chromium e un altro da WebKit (in precedenza condiviso con Chromium).

Una volta che la funzionalità sarà interoperabile, il nostro obiettivo è darti un maggiore controllo su come impostare lo stile dell'indicatore.

Altre demo

Per concludere, ecco altre demo da provare. Tutti utilizzano ::details-content.

Accordion di UIKit

Demo

Registrazione

Registrazione di https://codepen.io/web-dot-dev/pen/rNXrJyQ in Chrome 131

Questa demo è stata creata dopo UIKit Accordion. Il codice è praticamente lo stesso della versione della accordion di Material UI condivisa in precedenza.

Widget di informativa parzialmente aperto

Demo

Registrazione

Registrazione di https://codepen.io/web-dot-dev/pen/PoMBQmW in Chrome 131

Questa demo mostra un widget di informativa parzialmente aperto i cui contenuti sono già visibili sullo schermo. Per farlo, content-visibility è sempre impostato su visible. height viene animato utilizzando calc-size() perché è necessario un calcolo.

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

Per comodità, i contenuti vengono inseriti in un elemento div wrapper. A questo elemento vengono applicati gli stili di layout, come padding, e l'elemento ::details-content pseudo viene animato.