content-visibility: la nuova proprietà CSS che migliora le prestazioni del rendering

Migliora il tempo di caricamento iniziale saltando il rendering dei contenuti fuori schermo.

Vladimir Levin
Vladimir Levin

La proprietà content-visibility, lanciata in Chromium 85, potrebbe essere una delle nuove proprietà CSS di maggior impatto per migliorare le prestazioni di caricamento delle pagine. content-visibility consente allo user agent di saltare il lavoro di rendering di un elemento, compresi layout e disegno, fino a quando non è necessario. Poiché il rendering viene ignorato, se una gran parte dei tuoi contenuti non rientra nello schermo, l'utilizzo della proprietà content-visibility velocizza il caricamento iniziale dell'utente. Inoltre, consente interazioni più rapide con i contenuti sullo schermo. Piuttosto comodo.

demo con figure che rappresentano i risultati della rete
Nella demo dell'articolo, l'applicazione di content-visibility: auto ad aree di contenuti in blocchi offre un miglioramento delle prestazioni di rendering 7 volte al caricamento iniziale. Continua a leggere per saperne di più.

Supporto del browser

Supporto dei browser

  • 85
  • 85
  • 124

Fonte

content-visibility si basa sulle primitive contenute nella specifica di contenimento CSS. Sebbene al momento content-visibility sia supportato soltanto in Chromium 85 (e considerato "valido la prototipazione" per Firefox), la specifica di contenimento è supportata nella maggior parte dei browser più moderni.

Contenimento CSS

L'obiettivo principale e generale del contenimento CSS è consentire miglioramenti delle prestazioni di rendering dei contenuti web fornendo un isolamento prevedibile di un sottoalbero DOM dal resto della pagina.

Fondamentalmente, uno sviluppatore può indicare a un browser quali parti della pagina sono incapsulate come un insieme di contenuti, consentendogli di ragionare sui contenuti senza dover considerare lo stato al di fuori del sottoalbero. Sapere quali bit di contenuti (sottoalbero) contengono contenuti isolati significa che il browser può prendere decisioni di ottimizzazione per il rendering delle pagine.

Esistono quattro tipi di contenimento CSS, ciascuno dei quali rappresenta un valore potenziale per la proprietà CSS contain, che può essere combinato in un elenco di valori separato da spazi:

  • size: il contenimento delle dimensioni di un elemento garantisce che il riquadro dell'elemento possa essere disposto senza dover esaminare i relativi discendenti. Ciò significa che possiamo potenzialmente saltare il layout dei discendenti se tutto ciò di cui abbiamo bisogno è la dimensione dell'elemento.
  • layout: il contenimento del layout indica che i discendenti non influiscono sul layout esterno delle altre caselle nella pagina. In questo modo possiamo potenzialmente saltare il layout dei discendenti se vogliamo solo disporre le altre caselle.
  • style: il contenimento degli stili garantisce che le proprietà che possono avere effetti non solo sui relativi discendenti non eseguono l'escape dell'elemento (ad es. i contatori). In questo modo, possiamo potenzialmente saltare il calcolo dello stile per i discendenti se tutto ciò che vogliamo è calcolare gli stili su altri elementi.
  • paint: il contenimento della colorazione garantisce che i discendenti della casella contenitore non vengano visualizzati al di fuori dei suoi limiti. Non è possibile visualizzare nulla all'interno dell'elemento e, se un elemento è fuori schermo o non è visibile per altri motivi, anche i relativi discendenti non saranno visibili. In questo modo possiamo potenzialmente saltare il disegno dei discendenti se l'elemento è fuori schermo.

L'operazione di rendering non viene eseguita con content-visibility

Può essere difficile capire quali valori di contenimento utilizzare, poiché le ottimizzazioni del browser possono attivare solo quando viene specificato un set appropriato. Puoi sperimentare con i valori per capire cosa funziona meglio oppure utilizzare un'altra proprietà CSS chiamata content-visibility per applicare automaticamente il contenimento necessario. content-visibility ti garantisce i massimi risultati in termini di prestazioni che il browser può offrire con il minimo sforzo da parte tua in qualità di sviluppatore.

La proprietà di visibilità dei contenuti accetta diversi valori, ma auto è quello che fornisce miglioramenti immediati delle prestazioni. Un elemento con content-visibility: auto ottiene di contenimento layout, style e paint. Se l'elemento è fuori schermo e non è altrimenti pertinente per l'utente, gli elementi pertinenti sarebbero quelli con stato attivo o selezionato nel sottoalbero), guadagna anche il contenimento di size (e smette di mostrare i test di hit dei suoi contenuti).

Che cosa significa? In breve, se l'elemento è fuori schermo, i relativi discendenti non vengono visualizzati. Il browser determina le dimensioni dell'elemento senza considerare i suoi contenuti e si ferma qui. Gran parte del rendering, come lo stile e il layout del sottoalbero dell'elemento, viene saltata.

Man mano che l'elemento si avvicina all'area visibile, il browser non aggiunge più il contenimento size e inizia a colorare e a eseguire hit test dei contenuti dell'elemento. Ciò consente di eseguire il rendering in tempo per essere visto dall'utente.

Nota sull'accessibilità

Una delle caratteristiche di content-visibility: auto è che i contenuti fuori schermo rimangono disponibili nel modello a oggetti del documento e, di conseguenza, nell'albero dell'accessibilità (a differenza di visibility: hidden). Ciò significa che è possibile cercare i contenuti nella pagina e accedervi senza attendere il caricamento o sacrificare le prestazioni del rendering.

L'altro lato di questo, tuttavia, è che gli elementi dei punti di riferimento con funzioni di stile come display: none o visibility: hidden verranno visualizzati anche nell'albero dell'accessibilità quando sono fuori schermo, poiché il browser non eseguirà il rendering di questi stili finché non entreranno nell'area visibile. Per evitare che siano visibili nell'albero dell'accessibilità e che possano creare disordine, assicurati di aggiungere anche aria-hidden="true".

Esempio: un blog di viaggi

In questo esempio, facciamo riferimento al nostro blog di viaggi a destra e applichiamo content-visibility: auto alle aree suddivise a sinistra. I risultati mostrano i tempi di rendering che vanno da 232 ms a 30 ms al caricamento iniziale della pagina.

Un blog di viaggi in genere contiene un insieme di storie con alcune immagini e del testo descrittivo. Ecco cosa succede in un browser tipico quando visita un blog di viaggi:

  1. Una parte della pagina viene scaricata dalla rete, insieme a tutte le risorse necessarie.
  2. Il browser applica stili e layout a tutti i contenuti della pagina, senza considerare se i contenuti sono visibili all'utente.
  3. Il browser torna al passaggio 1 finché non sono state scaricate tutte le pagine e le risorse.

Nel passaggio 2, il browser elabora tutti i contenuti alla ricerca di elementi che potrebbero essere cambiati. Aggiorna lo stile e il layout di tutti i nuovi elementi, oltre agli elementi che potrebbero essere cambiati in seguito ai nuovi aggiornamenti. Questo è il lavoro di rendering. Questa operazione richiede tempo.

Uno screenshot di un blog di viaggi.
Un esempio di blog di viaggi. Consulta la demo su Codepen

Ora pensa a cosa succede se inserisci content-visibility: auto in ogni singola notizia del blog. Il loop generale è lo stesso: il browser scarica e visualizza i blocchi della pagina. Tuttavia, la differenza è nella quantità di lavoro che svolge nel passaggio 2.

Con la visibilità dei contenuti, applica uno stile e un layout a tutti i contenuti attualmente visibili all'utente (ossia, sullo schermo). Tuttavia, durante l'elaborazione della storia completamente fuori schermo, il browser ignorerà il lavoro di rendering e solo stile e layout del riquadro dell'elemento stesso.

Il caricamento di questa pagina sarebbe come se questa pagina contenga storie a schermo intero e caselle vuote per ciascuna delle notizie fuori schermo. Le prestazioni sono molto migliori, con una riduzione prevista del 50% o più del costo di rendering del caricamento. Nel nostro esempio, vediamo un aumento da un tempo di rendering di 232 ms a un tempo di rendering di 30 ms. Le prestazioni sono aumentate di 7 volte.

Qual è il lavoro che devi fare per ottenere questi vantaggi? Innanzitutto, suddividiamo i contenuti in sezioni:

Uno screenshot annotato della suddivisione dei contenuti in sezioni con una classe CSS.
Esempio di suddivisione dei contenuti in sezioni con la classe story applicata, per ricevere content-visibility: auto. Consulta la demo su Codepen

Successivamente, applichiamo la seguente regola di stile alle sezioni:

.story {
  content-visibility: auto;
  contain-intrinsic-size: 1000px; /* Explained in the next section. */
}

Specifica delle dimensioni naturali di un elemento con contain-intrinsic-size

Per poter usufruire dei potenziali vantaggi di content-visibility, il browser deve applicare un contenimento delle dimensioni per garantire che i risultati del rendering dei contenuti non influiscano in alcun modo sulle dimensioni dell'elemento. Ciò significa che l'elemento viene visualizzato come se fosse vuoto. Se per l'elemento non è specificata l'altezza in un normale layout a blocchi, l'altezza sarà pari a 0.

Questa soluzione potrebbe non essere l'ideale, dato che la dimensione della barra di scorrimento sarà dipendente da ogni storia che ha un'altezza diversa da zero.

Fortunatamente, CSS fornisce un'altra proprietà, contain-intrinsic-size, che specifica in modo efficace la dimensione naturale dell'elemento se l'elemento è influenzato dal contenimento delle dimensioni. Nel nostro esempio, lo stiamo impostando su 1000px come stima dell'altezza e della larghezza delle sezioni.

Ciò significa che verrà visualizzato come se avesse un singolo elemento secondario di dimensioni "intrinseche", garantendo che i div non di dimensioni sufficienti occupino ancora spazio. contain-intrinsic-size funge da dimensione segnaposto al posto dei contenuti visualizzati.

A partire da Chromium 98, è disponibile una nuova parola chiave auto per contain-intrinsic-size. Se specificato, il browser memorizzerà l'ultima dimensione di rendering, se presente, e la utilizzerà al posto della dimensione segnaposto fornita dallo sviluppatore. Ad esempio, se hai specificato contain-intrinsic-size: auto 300px, l'elemento inizierà con un dimensionamento intrinseco 300px in ogni dimensione, ma, una volta eseguito il rendering dei contenuti, manterrà la dimensione intrinseca visualizzata. Verranno memorizzate anche eventuali modifiche successive alle dimensioni di rendering. In pratica, ciò significa che se scorri un elemento con l'opzione content-visibility: auto applicato e poi lo scorri indietro fuori schermo, questo manterrà automaticamente la larghezza e l'altezza ideali e non ripristinerà le dimensioni del segnaposto. Questa funzionalità è particolarmente utile per gli scorrimenti continui, che ora possono migliorare automaticamente la stima delle dimensioni nel tempo mentre l'utente esplora la pagina.

Contenuti nascosti con content-visibility: hidden

E se volessi mantenere i contenuti non sottoposti a rendering indipendentemente dal fatto che siano sullo schermo o meno, sfruttando al contempo i vantaggi dello stato di rendering memorizzato nella cache? Inserisci: content-visibility: hidden.

La proprietà content-visibility: hidden offre tutti gli stessi vantaggi dei contenuti non sottoposti a rendering e dello stato di rendering memorizzato nella cache di content-visibility: auto quando non è visualizzato nella schermata. Tuttavia, a differenza di auto, la visualizzazione sullo schermo non inizia automaticamente.

Questo ti offre un maggiore controllo, consentendoti di nascondere i contenuti di un elemento e poi mostrarli rapidamente in un secondo momento.

Confrontalo con altri modi comuni per nascondere i contenuti dell'elemento:

  • display: none: nasconde l'elemento e distrugge il suo stato di rendering. Ciò significa che mostrare l'elemento è costoso quanto visualizzare un nuovo elemento con gli stessi contenuti.
  • visibility: hidden: nasconde l'elemento e mantiene il suo stato di rendering. Ciò non rimuove l'elemento dal documento poiché quest'ultimo (e il suo sottoalbero) occupa ancora spazio geometrico sulla pagina e su cui è ancora possibile fare clic. Inoltre, aggiorna lo stato di rendering ogni volta che è necessario, anche quando è nascosto.

content-visibility: hidden, invece, nasconde l'elemento mantenendo il suo stato di rendering, pertanto, se vengono apportate modifiche, vengono applicate solo quando l'elemento viene mostrato di nuovo, ovvero la proprietà content-visibility: hidden viene rimossa.

Alcuni ottimi casi d'uso per content-visibility: hidden sono l'implementazione di dispositivi di scorrimento virtuali avanzati e la misurazione del layout. Sono ideali anche per le applicazioni a pagina singola (APS). Le visualizzazioni delle app inattive possono essere lasciate nel DOM con l'applicazione content-visibility: hidden per impedirne la visualizzazione, ma mantenere lo stato memorizzato nella cache. In questo modo la visualizzazione viene visualizzata rapidamente quando diventa di nuovo attiva.

Effetti sull'interazione con il colore successivo (INP)

INP è una metrica che valuta la capacità di una pagina di rispondere in modo affidabile all'input degli utenti. La reattività può essere influenzata da un eventuale lavoro eccessivo svolto sul thread principale, compreso quello di rendering.

Ogni volta che riesci a ridurre il lavoro di rendering in una determinata pagina, dai al thread principale l'opportunità di rispondere più rapidamente agli input utente. Ciò include il lavoro di rendering e l'utilizzo della proprietà CSS content-visiblity, ove appropriato, può ridurre il lavoro di rendering, soprattutto durante l'avvio, quando viene svolta la maggior parte delle operazioni di rendering e layout.

La riduzione del lavoro di rendering ha un effetto diretto su INP. Quando gli utenti tentano di interagire con una pagina che utilizza la proprietà content-visibility correttamente per rimandare il layout e il rendering degli elementi fuori schermo, dai al thread principale la possibilità di rispondere al lavoro critico visibile all'utente. In alcune situazioni, questa operazione può migliorare l'INP della tua pagina.

Conclusione

content-visibility e la specifica di contenimento CSS indicano che il tuo file CSS potrà usufruire di alcuni entusiasmanti miglioramenti delle prestazioni. Per maggiori informazioni su queste proprietà, consulta: