È un’esperienza a dir poco frustante: iniziamo a leggere un contenuto online quando, all’improvviso, la pagina salta tipo centinaia o migliaia di pixel e ci fa perdere completamente il punto in cui eravamo, oppure cerchiamo di fare tap su un pulsante e compare al suo posto un popup che premiamo involontariamente, portandoci su una pagina indesiderata da cui cerchiamo disperatamente di tornare indietro. Sono due esempi di (terribili) layout shift, spostamenti di layout della pagina web che possono causare difficoltà all’esperienza dell’utente: non a caso Google ha inserito il Cumulative Layout Shift tra le metriche dei Core Web Vitals, e ora ci guida a misurare e ottimizzare questa metrica per migliorare la fruizione delle nostre pagine.

Variazione cumulativa del layout o CLS: che cosa significa questa metrica

L’approfondimento è curato ancora una volta da Patrick Kettner, Developer Advocate di Google che già aveva dedicato dei video alla gestione degli altri due Core Web Vitals, con consigli per misurare il FID e per ottimizzare il LCP.

Nel nuovo (e ultimo) episodio su YouTube di questa serie ci concentriamo quindi sul Cumulative Layout Shift o CLS (in italiano variazione cumulativa del layout), un parametro che ci aiuta a comprendere quanto sia stabile una pagina o, più precisamente, quanto è prevedibile l’uso di una pagina.

Patrick Kettner di Google

Tutte le parti visibili di una pagina e il modo in cui si incastrano tra loro, ci spiega Kettner, costituiscono ciò che un browser considera un layout – immagini, testo, video, tutto quanto. Quando il contenuto di una pagina cambia, ad esempio quando viene inserita una pubblicità, viene caricato un widget, o cambia dimensione un’immagine, può succedere a volte che le cose che sono già visibili nella pagina finiscano per essere spostate altrove per far sì che tutto si adatti e “ogni volta che questo accade si verifica una variazione di layout“.

Il cumulative layout shift è quindi un modo per determinare quanto delle parti visibili di una pagina, in percentuale, sperimentano queste variazioni di layout.

Un esempio di CLS

Nel video, il Googler porta l’esempio di un semplice articolo di blog, che mostra in pagina un titolo, un’immagine principale e del testo. Per gli utenti che navigano da una connessione più lenta, il testo appare subito, ma l’immagine richiede un po’ più di tempo per apparire, anche se alla fine sarà scaricata e aperta.

Esempi di variazione di layout

Tuttavia, prima che i pixel di quelle immagini possano essere dipinti, potrebbero essere necessari alcuni cambiamenti.

Per quanto riguarda il browser, tutto ciò che sta sopra all’immagine è a posto e non c’è bisogno di cambiare nulla, ma affinché l’immagine appaia nel posto e nel modo in cui è stata concepita, tutto ciò che sta sotto di essa deve spostarsi verso il basso per farle spazio.

Cumulative Layout Shift di una pagina, i consigli di Google

Quindi, il testo dell’articolo viene letteralmente spinto in basso per metà della quantità visibile della pagina per fare spazio all’immagine: ciò significa che il 50% di ciò che possiamo vedere inizialmente deve essere spostato solo perché l’immagine appaia, e quindi il CLS sarà 0,5 – ma solo se nient’altro si sposta sulla pagina o se l’utente esce dalla pagina prima che qualcos’altro modifichi il layout, perché altrimenti il CLS sarà peggiore.

In sostanza, pertanto, il punteggio CLS di una pagina indica quanto cambiano le parti visive della stessa, ma Kettner ci spiega che ci sono alcune precauzioni e aspetti da non trascurare.

  1. Ci può essere un solo punteggio CLS

Ogni volta che qualcuno visita il sito, il browser traccerà continuamente il CLS per tutto il tempo di utilizzo, e quando l’utente esce dalla pagina o chiude la scheda riporterà il più grande valore CLS trovato. Questo singolo numero viene raccolto con quello di tutti gli altri visitatori di quell’URL e genera il valore CLS per i Web vitals di quella pagina.

  1. A volte il cambiamento è positivo

“Se le pagine non cambiassero mai, non sarebbero così utili”, ragiona Kettner: alcuni cambiamenti di layout innescati dalle interazioni dell’utente – cose come toccare, cliccare o digitare – hanno un periodo di grazia di 500 millisecondi in cui eseguire qualsiasi cambiamento di layout di cui hanno bisogno per rispondere al meglio a quell’utente. Dopo questi 500 millisecondi, inizia una nuova finestra di sessione CLS: dal millisecondo 501 in poi, qualsiasi spostamento di contenuto che si verifica viene sommato e potenzialmente utilizzato per un punteggio finale CLS, e questa finestra di sessione rimarrà aperta per tutto il tempo in cui ci sono layout visibili che vengono spostati.

Rappresentazione della finestra di grazia

Qualsiasi spostamento aggiuntivo viene sommato insieme: ad esempio, un’altra pagina del nostro sito presenta un layout basic, con un titolo e un corpo di testo, ma questa volta ha due immagini più piccole che, come nel caso precedente, sono lente da caricare e fanno spostare il contenuto quando appaiono. La prima foto sposta il layout solo di una piccola quantità, del 5% e quindi il suo CLS sarebbe 0,05, ma la seconda immagine viene caricata diverse centinaia di millisecondi dopo e ha bisogno di un po’ di spazio, spingendo il contenuto ancora più in basso, per una quantità visibile del 2,5%. Questi due eventi avvengono in tempi vicini e quindi le variazioni sono accumulate in un unico valore CLS, che è del 7,5% o 0,075.

La finestra della sessione, infatti, rimane aperta finché non è passato più di un secondo dall’ultimo spostamento di layout, o finché non sono passati cinque secondi dalla creazione di questa finestra di sessione: qualsiasi variazione di layout successiva viene contata come un evento separato e non aggiunta alla finestra precedente.

  1. Non tutte le interazioni sono libere

Le interazioni dell’utente come lo scorrimento o il movimento del mouse non contano come la tipologia di eventi che aprono il periodo di grazia di 500 millisecondi, perché in effetti “un utente non può aspettarsi che il layout di una pagina si sposti mentre la sta scorrendo”.

  1. Non tutti i cambiamenti sono negativi

È possibile spostare a piacimento il contenuto della pagina tramite animazioni e trasformazioni CSS.

Effetto dell'attributo transform in CSS

Impostando un attributo CSS come transform, infatti, l’elemento viene spostato su un suo livello specifico e la sua posizione non impatta sul layout di alcuna altra parte della pagina, ma “è come se galleggiasse in cima a tutto il resto” e non conta per il CLS.

  1. Quello che non possiamo vedere non può farci male

Il CLS vale solo per gli elementi visibili della pagina e, per questa metrica, “non importa se si muove qualcosa che non si può vedere”. Rispettando la filosofia della Page Experience, il CLS serve ad assicurarsi che le persone abbiano la migliore esperienza utente possibile: quindi, possiamo spostare qualcosa o mettere un contenuto in lazy loadingse non è visibile all’utente” e senza influenzare il CLS.

I punteggi CLS: come misurarli e quali sono i valori buoni

C’è una cosa fondamentale da ricordare: un buon punteggio CLS significa che ciò che l’utente vede è stabile e prevedibile e che non sta saltando tutto intorno.

Dal punto di vista pratico, il CLS è rappresentato da un numero compreso tra 0 e 1, con lo 0 che rappresenta il punteggio perfetto “in un mondo ideale” perché, per il Googler, “non c’è quasi mai bisogno che si verifichi uno spostamento di layout e possiamo quasi sempre prevenirli”; tuttavia, nel modo reale “abbiamo tutti un lavoro e i nostri siti stanno affrontano tonnellate di preoccupazioni diverse”.

Indicazione di un buon punteggio CLS

Quindi, se raggiungere lo 0 è quasi impossibile, “un ottimo numero a cui puntare è il 75% o più delle visualizzazioni di una pagina che abbia un CLS di 0.1 o meno”, dice Kettner. Se riusciamo a stare al di sotto di questa soglia, le pagine offrono un’esperienza visiva stabile, mentre se superiamo tali valori ci sono alcuni metodi per migliorare la situazione e ridurre il CLS.

Come misurare il Cumulative Layout Shift

Come per tutti i Core Web Vitals, il CLS indica “ciò che gli utenti reali stanno sperimentando quando usano il nostro sito”, mostrando informazioni che si definiscono dati sul campo (field data), che è possibile ritrovare negli analytics personali o nelle metriche presenti all’interno della sezione Core Web Vitals di Search Console.

Search Console, fattori per la Page Experience e Core Web Vitals hanno tutti la stessa fonte per il risultato CLS delle pagine, ovvero il Chrome User Experience Report o CrUX, che presenta metriche anonimizzate sui tempi prestazionali riscontrati dagli utenti effettivi che visitano gli URL del sito.

Per sua natura, CrUX non si aggiorna istantaneamente e “può richiedere fino a un mese la pubblicazione della pagina per iniziare a fonire i dati sul campo”.

Per fortuna, non serve aspettare così a lungo per avere un’idea di come si comporta per il CLS la pagina su cui stiamo lavorando, perché possiamo usare strumenti come Google Lighthouse, che fornisce rapidamente gli stessi dati sul campo che abbiamo in Search Console per qualsiasi pagina oppure permette di generare dati di laboratorio.

I dati di laboratorio sono un “tentativo di indovinare nel modo più verosimile come saranno i dati di campo”, si basano su dispositivi mobili medi e sulla velocità media di Internet da mobile; ad ogni modo, restano un’ipotesi, possono cioè essere utili per indicarci la giusta direzione ma “i dati sul campo sono l’unico valore che l’esperienza sulla pagina, e quindi la Ricerca, guarderanno effettivamente”.

Ad esempio, se i nostri utenti hanno dispositivi di fascia alta o connessioni insolitamente lente, è probabile che ci sia un forte scarto differenziale tra i valori dei dati di laboratorio e quelli sul campo.

L’analisi del CLS con JavaScript

I dati di laboratorio possono essere davvero utili, dice Kettner, ma dopo aver pubblicato effettivamente la pagina è “un po’ più utile raccogliere effettivamente i dati CLS tramite i nostri analytics“, e in particolare attraverso la misurazione con JavaScript attraverso il performance observer utilizzato anche per le altre metriche.

Performance observer è una browser API relativamente nuova che permette di sottoscrivere gli eventi che accadono nel browser relativi alle prestazioni.

Come usare la funzione Performance Observer per il CLS

Non abbiamo la possibilità di osservare direttamente il valore di cumulative layout shift, ma “abbiamo tutti i pezzi giusti di cui abbiamo bisogno per scoprilo da soli”: il primo passo è sottoscrivere il performance event “layout shift”, in modo che il nostro codice sia chiamato ogni volta che il browser ha un evento di variazione del layout e capire come sarà il CLS per questo utente.

Quando la nostra funzione viene chiamata, ottiene una entry list di ogni variazione di layout che è stata osservata: possiamo chiamare Get Entries su questa entry list per ottenere un array di voci da ripetere su ogni singola voce, e poi ancora controllare se una voce ha avuto un input recente (HadRecentInput, una comoda proprietà fornita dal browser su ogni layout shift entry).

Se “HadRecentInput” è vero, allora siamo in quella prima finestra di grazia di 500 millisecondi e possiamo ignorare questa voce; al contrario, se “HadRecentInput” è falso, dobbiamo prendere entry.value e aggiungerlo al nostro CLS.

 

In origine, il CLS veniva calcolato sommando tutta la sessione di una pagina, ma in seguito ai feedback ricevuti e all’evoluzione continua Google ha modificato la metrica e scelto di usare la metodologia della finestra di sessione – ne abbiamo parlato anche qui. Per calcolare il CLS nella misura in cui è inteso oggi dobbiamo quindi aggiungere altre variabili al nostro codice JS, come mostrato in questa immagine.

Codice JS per misurare CLS

Ora che sappiamo come raccogliere il valore CLS, “abbiamo ancora bisogno di innescare un evento analytics“, ma il modo in cui lo faremo dipendono esclusivamente dalla nostra infrastruttura, mentre il quando vale per tutti.

Il browser ha un altro evento, chiamato visibility change (cambiamento di visibilità), che viene attivato ogni volta che la visibilità di una pagina cambia, come quando viene ridotta a icona, chiusa, o si naviga altrove (in un altro tab o finestra, ad esempio) e ci permette di espandere il nostro codice per includere il reporting.

Proprietà visibility change

Se lo stato di visibilità è hidden (nascosto), possiamo chiamare take records sul nostro PerformanceObserver: avremo così una lista di tutte le voci che non sono state elaborate dal nostro codice, e possiamo quindi elaborare ogni voce proprio come faremmo normalmente, per poi chiamare sendCLSToTheServer – una funzione completamente inventata che dobbiamo implementare per farla funzionare sul nostro sito.

L’unica stranezza rimasta nel nostro codice, prosegue Kettner, “è che per assicurarci che il CLS sia sempre inviato quando la gente lascia la pagina, stiamo usando l’evento di visibility change“, che potenzialmente rischia di inviare più eventi analytics per lo stesso utente (ad esempio, un utente che ha la nostra pagina aperta, ma poi cambia scheda, e torna indietro, e poi di nuovo, e ancora e ancora, invia più eventi al server ogni volta che avviene il cambio).

Pertanto, sarà necessario filtrare questi valori sul back-end per ottenere il valore più grande per ogni sessione utente, ricordando come detto che ci può essere solo un valore Cumulative Layout Shift.

Come migliorare i punteggi CLS

Per migliorare il valore del Cumulative Layout Shift dobbiamo innanzitutto capire che cosa causa le variazioni negative per l’esperienza utente e, secondo il video, questi cambiamenti di layout “possono essere ricondotti a una manciata di cause”, come ad esempio immagini che non hanno dimensioni inline, iframes o embed che non hanno dimensioni inline, contenuto iniettato dinamicamente che non preserva lo spazio con dimensioni esplicite e infine web font o font di icone che causano un flash di testo non stilizzato o invisibile.

Le 4 fonti di problemi con CLS

Variazioni di layout: le cause più frequenti di problemi e come risolverli

Le immagini sono la principale fonte di problemi con il CLS, sostiene Kettner.

Ricordando il precedente esempio, un’immagine che non include un attributo di larghezza o altezza, sia in linea che con il proprio CSS, dovrebbe essere in realtà solo una nota segnaposto (placeholder note), qualcosa che è completamente diverso dalla dimensione che avrà alla fine del caricamento, e che provoca il salto del contenuto, innescando uno spostamento del layout.

La soluzione a questo problema è molto semplice: includere esplicitamente gli attributi di altezza e larghezza della nostra immagine. Tali “attributi esistono da decenni e inserirli era una pratica comune, ma con il responsive design e gli schermi ad alta definizione l’impostazione di questi valori è diventata meno utile rispetto all’uso di CSS o lasciare che il browser li capisca da solo”.

Attualmente, tutti i browser moderni fanno dimensionamento automatico della risorsa in base al rapporto d’aspetto (aspect ratio), cioè a quanto è larga un’immagine divisa per quanto è alta secondo i valori di larghezza e altezza. Questo significa che “possiamo ancora modellare l’immagine usando valori reattivi come width 100% nel nostro CSS”, ma che al tempo stesso i browser riservano automaticamente l’altezza corretta in base al rapporto di aspetto della larghezza e altezza che forniamo.

Oltre a essere una soluzione valida per gestire l’aspetto delle immagini su tutti i dispositivi, questo impedirà anche alle immagini di innescare il CLS, perché non si vedranno variazioni di layout, anche se l’immagine viene caricata su una connessione più lenta.

Un altro fronte critico sono iframes ed embed, che “possono significare un sacco di cose diverse, come slot pubblicitari o widget per un lettore video”; in pratica, qualsiasi cosa che carichiamo da un altro dominio o da un altro servizi è probabile che sia caricata all’interno di un iframe o di un embed.

Non possiamo controllare cosa succede dentro l’iframe, dice il Googler, ma possiamo controllare cosa succede intorno ad esso: proprio come le nostre immagini, abbiamo bisogno di riservare uno spazio che sarà occupato dall’iframe. Impostando altezze e larghezze esplicite per l’elemento parent dell’iframe, il browser gli riserva lo spazio, impedendo così qualsiasi tipo di spostamento di layout.

A volte, l’ad network che fornisce gli ads per il sito non serve la dimensione giusta per il suo slot, che potrebbe essere troppo grandi di un paio di pixel: Kettner consiglia quindi di impostare esplicitamente Overflow Hidden su tali iframe parent container per essere sicuri che non eccedano le misure in maniera inattesa. Ma se dobbiamo essere certi che ogni singolo pixel di un annuncio sia visibile, dobbiamo sovradimensionare lo slot del parent container ad e modificare di conseguenza il nostro design per tenerne conto e farlo apparire in maniera buona anche se le dimensioni sono maggiori. Inoltre, è utile anche evitare di far collassare gli slot pubblicitari quando nessun annuncio viene restituito, perché la rimozione di tutto quello spazio causerà altrettante variazioni fastidiose di layout.

Non tutti i contenuti dinamicamente caricati sono in iframe, però: se il nostro sito ha una lista di articoli o pagine di prodotti a scorrimento infinito, o se mettiamo semplicemente qualsiasi tipo di contenuto in lazy loading, dobbiamo sempre essere sicuri di riservare lo spazio che servirà con un’altezza e una larghezza esplicite.

Proprio come con gli iframe, se tutto va bene il server dovrebbe restituire qualcosa di queste dimensioni, ma teoricamente “le nostre pagine sono progettate in modo per essere abbastanza flessibili da gestire contenuti più grandi o più piccolo del previsto”.

E quindi, impostare una larghezza e un’altezza flessibili ma immutabili e altezza sulle risorse remote della nostra pagina “è la chiave per un punteggio CLS minimo”.

La gestione dei web font per il CLS

Gli esempi precedenti di potenziali cause di CLS elevato si possono risolvere semplicemente “assicurandoci che tutti i rettangoli abbiano dimensioni esplicite che non cambiano“, sintetizza Kettner, ma cosa facciamo se è il contenuto all’interno di quei rettangoli a cambiare?

Questo è il motivo per cui i web font pongono una sfida unica a CLS, perché non possiamo impostare esplicitamente una larghezza o un’altezza sul testo, e quindi per risolvere i problemi di un web font o un font di icone che causano uno spostamento del layout abbiamo bisogno di un approccio diverso.

La soluzione più semplice è non usare il font. Nel caso di icon fonts, in realtà è molto meglio usare direttamente gli SVG oggi, perché “non solo hanno una capacità di design notevolmente migliorata, ma danno molti meno problemi nei browser moderni e sono anche sostanzialmente meglio per l’accessibilità“.

Ma se è un web font a causare la variazione di layout e vogliamo assolutamente usarlo, allora dobbiamo ottimizzare il modo in cui il font viene caricato. In breve, un ottimo punto di partenza è utilizzare il preload per tutti i font che stiamo davvero utilizzando: solitamente, i font web sono caricati in modo asincrono (lazy load) e quindi il browser scarica l’HTML, qualsiasi JavaScript e il CSS prima di iniziare a scaricare ed elaborare ogni font face declaration che dichiariamo all’interno di quel CSS. Link rel preload è una sorta di suggerimento che possiamo dare al browser per fargli iniziare a scaricare il font prima che lo scopra nel modo normale, così che sarà pronto molto più velocemente quando è scoperto.

Inoltre, questi font essenziali devono essere messi il più vicino possibile alla parte superiore della pagina, per dare al browser più tempo possibile.

Invece, se scegliamo il web font per una questione estetica, possiamo in alternativa font display: optional, una proprietà che possiamo impostare in una font face declaration, che supporta alcuni valori diversi e che, con optional, dice al browser che il font è, appunto, opzionale. In pratica, impostando questo valore, se il web font impiega più di tre secondi a caricarsi il browser rinuncerà a cercare di caricarlo, e mostrerà solo qualsiasi cosa sia stata già renderizzata. Quindi, Quindi niente più cambiamenti, niente più spostamenti di contenuto.

Come impostare la funzionalità opzionale ai font

Quando stiamo già guardando un codice basato su font, dobbiamo controllare di non aver già usato font display: swap, che fa più o meno la cosa opposta di optional: font display swap dice al browser di mostrare subito qualsiasi font di ripiego esistente e poi sostituirlo con il font che stiamo richiedendo non appena finisce il download, a prescindere dal tempo necessario per scaricarlo.

Se usiamo un font web che è lento da caricare su una parte sostanziale della tua pagina “possiamo immaginare quanto grande possa essere il tuo punteggio CLS se usiamo lo swap di visualizzazione dei font”, conclude Kettner.