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 il rendimento del caricamento delle pagine. content-visibility consente allo user agent di saltare il lavoro di rendering di un elemento, inclusi layout e disegno, finché non è necessario. Poiché il rendering viene ignorato, se una gran parte dei contenuti è fuori 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 di rete
Nella demo del nostro articolo, l'applicazione di content-visibility: auto ad aree di contenuti suddivisi in blocchi consente un aumento delle prestazioni del rendering di 7 volte al caricamento iniziale. Continua a leggere per saperne di più.

Supporto del browser

Supporto dei browser

  • 85
  • 85
  • 124

Origine

content-visibility si basa su primitive all'interno della Specifica di contenimento CSS. Sebbene al momento content-visibility sia supportato solo in Chromium 85 (e ritenuto "vale la pena eseguire la prototipazione" per Firefox), la Specifica di contenimento è supportata nella maggior parte dei browser moderni.

Contenimento CSS

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

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

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

  • size: il contenimento delle dimensioni su un elemento garantisce che la scatola dell'elemento possa essere disposta senza dover esaminare i suoi 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 significa che i discendenti non influiscono sul layout esterno di altre caselle nella pagina. In questo modo, potremmo saltare il layout dei discendenti se tutto quello che vogliamo fare è disporre altre caselle.
  • style: il contenimento degli stili garantisce che le proprietà che possono avere effetti su di più dei suoi discendenti non sfuggono all'elemento (ad es. i contatori). In questo modo potremo saltare il calcolo degli stili per i discendenti se vogliamo solo calcolare gli stili su altri elementi.
  • paint: il contenimento della vernice garantisce che i discendenti della casella contenitore non vengano visualizzati al di fuori dei relativi limiti. L'elemento non può sovraccaricare l'elemento e, se un elemento è fuori schermo o non visibile per altri motivi, anche i relativi discendenti non saranno visibili. In questo modo potremo saltare la pittura dei discendenti se l'elemento è fuori schermo.

Omissione lavoro di rendering con content-visibility

Può essere difficile capire quali valori di contenimento utilizzare, poiché le ottimizzazioni del browser possono essere attivate solo quando viene specificato un insieme appropriato. Puoi sperimentare i valori per vedere cosa funziona meglio oppure utilizzare un'altra proprietà CSS chiamata content-visibility per applicare automaticamente il contenuto necessario. content-visibility ti garantisce di ottenere i massimi miglioramenti 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 è quella che offre miglioramenti immediati delle prestazioni. Un elemento con content-visibility: auto ottiene contenimento layout, style e paint. Se l'elemento è fuori dallo schermo (e non è altrimenti pertinente per l'utente, gli elementi rilevanti sono quelli che hanno lo stato attivo o la selezione nel sottoalbero), riceve anche il contenimento di size (e smette di dipingere e di eseguire l'hit test 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 considerarne i contenuti e si ferma qui. Viene saltata la maggior parte del rendering, ad esempio lo stile e il layout del sottoalbero dell'elemento.

Quando l'elemento si avvicina all'area visibile, il browser non aggiunge più il contenuto size e inizia a dipingere e eseguire l'hit test dei contenuti dell'elemento. In questo modo il lavoro di rendering può essere eseguito appena in tempo per essere visualizzato dall'utente.

Una 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 contenuti nella pagina e raggiungerli, senza attendere che vengano caricati o sacrificare le prestazioni di rendering.

Il rovescio della medaglia, tuttavia, è che gli elementi punti di riferimento con funzionalità di stile come display: none o visibility: hidden appariranno anche nell'albero dell'accessibilità quando fuori dallo 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à, creando potenzialmente disordine, assicurati di aggiungere anche aria-hidden="true".

Esempio: un blog di viaggi

In questo esempio, abbiamo basato il nostro blog di viaggi a destra e applichiamo content-visibility: auto ad aree suddivise a sinistra. I risultati mostrano tempi di rendering compresi tra 232 ms e 30 ms al caricamento iniziale della pagina.

In genere, un blog di viaggi contiene una serie di storie con alcune immagini e un testo descrittivo. Ecco cosa succede in un browser tipico quando accede a un blog di viaggi:

  1. Una parte della pagina viene scaricata dalla rete, insieme a tutte le risorse necessarie.
  2. Il browser applica uno stile e un 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 vengono scaricate tutte le risorse e la pagina.

Nel passaggio 2, il browser elabora tutti i contenuti alla ricerca di elementi che potrebbero essere cambiati. Consente di aggiornare lo stile e il layout di tutti i nuovi elementi, nonché di quelli che potrebbero essere stati spostati in seguito ai nuovi aggiornamenti. Si tratta del lavoro di rendering. Questa operazione richiede tempo.

Uno screenshot di un blog di viaggi.
Un esempio di blog di viaggi. Vedi Demo su Codepen

Pensa ora a cosa succede se inserisci content-visibility: auto in ogni singola storia del blog. Il loop generale è lo stesso: il browser scarica ed esegue il rendering dei blocchi della pagina. Tuttavia, la differenza sta nella quantità di lavoro che svolge nel secondo passaggio.

Con la visibilità dei contenuti, definisce e definisce il layout e lo stile di tutti i contenuti attualmente visibili all'utente (sono sullo schermo). Tuttavia, durante l'elaborazione della storia completamente fuori schermo, il browser ignorerà il lavoro di rendering e impiegherà solo lo stile e il layout della casella dell'elemento.

Il caricamento di questa pagina sarebbe come se contenesse storie complete sullo schermo e caselle vuote per ogni storia fuori schermo. Il risultato è molto migliore, con una riduzione prevista del 50% o più dal costo di rendering del caricamento. Nel nostro esempio, vediamo un aumento, passando da un tempo di rendering di 232 ms a un tempo di rendering di 30 ms. Si tratta di un aumento delle prestazioni di 7 volte.

Cosa devi fare per usufruire di questi vantaggi? Per prima cosa, suddividiamo il contenuto in sezioni:

Uno screenshot con annotazioni del chunking dei contenuti in sezioni con una classe CSS.
Esempio di suddivisione del contenuto in sezioni in cui è applicata la classe story, per ricevere content-visibility: auto. Vedi Demo su Codepen

Quindi, applichiamo alle sezioni la seguente regola di stile:

.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 realizzare i potenziali vantaggi di content-visibility, il browser deve applicare il contenimento delle dimensioni per garantire che i risultati di rendering dei contenuti non influiscano in alcun modo sulle dimensioni dell'elemento. Ciò significa che l'elemento apparirà come se fosse vuoto. Se l'elemento non ha un'altezza specificata in un layout a blocchi regolare, avrà un'altezza pari a 0.

Questo potrebbe non essere l'ideale, poiché la dimensione della barra di scorrimento cambierà, dipendendo da ogni storia con un'altezza diversa da zero.

Per fortuna, il CSS fornisce un'altra proprietà, contain-intrinsic-size, che specifica effettivamente la dimensione naturale dell'elemento se quest'ultimo è interessato dal contenimento delle dimensioni. Nel nostro esempio, l'impostazione è 1000px come stima dell'altezza e della larghezza delle sezioni.

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

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

I contenuti vengono nascosti con content-visibility: hidden

Cosa succede se vuoi che i contenuti non vengano sottoposti a rendering indipendentemente dal fatto che siano visualizzati o meno sullo schermo, 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 fuori schermo. Tuttavia, a differenza di auto, la visualizzazione sullo schermo non inizia automaticamente.

In questo modo, hai un maggiore controllo, puoi nascondere i contenuti di un elemento e in seguito mostrarli rapidamente.

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

  • display: none: nasconde l'elemento e ne distrugge lo stato di rendering. Ciò significa che scoprire l'elemento è costoso quanto visualizzare un nuovo elemento con gli stessi contenuti.
  • visibility: hidden: nasconde l'elemento e conserva lo stato di rendering. In questo modo l'elemento non viene rimosso dal documento, poiché l'elemento (e il relativo sottoalbero) occupano ancora uno spazio geometrico sulla pagina, su cui è comunque possibile fare clic. Inoltre, aggiorna lo stato del rendering ogni volta che è necessario, anche quando è nascosto.

content-visibility: hidden, invece, nasconde l'elemento conservando il suo stato di rendering, quindi, se devono essere apportate delle modifiche, queste 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 scorrimento virtuali avanzati e del layout di misurazione. Sono perfette anche per le applicazioni a pagina singola (APS). Le visualizzazioni delle app inattive possono essere lasciate nel DOM con l'applicazione content-visibility: hidden, che ne impedisce la visualizzazione e mantiene lo stato nella cache. In questo modo il rendering della visualizzazione diventa più veloce quando torna attiva.

Effetti sull’interazione con Next Paint (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 una quantità eccessiva di lavoro sul thread principale, incluso il lavoro di rendering.

Ogni volta che puoi ridurre il lavoro di rendering su una determinata pagina, offri al thread principale l'opportunità di rispondere più rapidamente agli input degli utenti. 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 eseguita 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 correttamente la proprietà content-visibility per rinviare il layout e il rendering degli elementi fuori schermo, offri al thread principale la possibilità di rispondere a lavori critici visibili all'utente. Questo può migliorare l'INP della pagina in alcune situazioni.

Conclusione

content-visibility e la specifica di contenimento CSS indicano che sono in arrivo alcuni incredibili incentivi per il rendimento del tuo file CSS. Per saperne di più su queste proprietà, dai un'occhiata a: