⚡ Prestazioni web

CLS: eliminare gli spostamenti di layout una causa alla volta

Le cause più comuni del Cumulative Layout Shift, da immagini senza dimensioni a banner e font, con le correzioni CSS e HTML che rendono la pagina stabile.

Capita a tutti: si sta per toccare un link e, un attimo prima, il testo scivola verso il basso perché sopra è comparso un banner. Il Cumulative Layout Shift misura proprio questo fastidio. Un valore fino a 0,1 è considerato buono, oltre 0,25 è scarso. A differenza di LCP e INP, il CLS non è un tempo ma un punteggio senza unità, e si può quasi sempre portare vicino a zero con interventi di HTML e CSS, senza toccare il server.

Come si calcola, in breve

Ogni spostamento inatteso riceve un punteggio dato dal prodotto di due fattori: quanta parte del viewport è occupata dagli elementi instabili (frazione di impatto) e di quanto si sono spostati rispetto all'altezza o larghezza del viewport (frazione di distanza). Gli spostamenti vicini nel tempo vengono raggruppati in finestre, e il CLS della pagina è il valore della finestra peggiore, non la somma di tutta la visita.

Un dettaglio importante: gli spostamenti che avvengono entro mezzo secondo da un'interazione dell'utente, come l'apertura di una fisarmonica dopo un clic, non vengono conteggiati. Il CLS penalizza ciò che l'utente non si aspetta.

Causa 1: immagini e video senza dimensioni

Se un tag img non ha width e height, il browser non sa quanto spazio riservare finché il file non arriva, e tutto il contenuto sotto viene spinto in basso. La soluzione è indicare sempre le dimensioni intrinseche: i browser moderni le usano per calcolare il rapporto d'aspetto anche quando il CSS rende l'immagine fluida.

<img src="foto.webp" width="1600" height="900" alt="…">
img { max-width: 100%; height: auto; }

Per contenitori senza un'immagine nativa, come un iframe di una mappa o un riquadro video incorporato, si usa la proprietà aspect-ratio:

.video-incorporato { aspect-ratio: 16 / 9; width: 100%; }

Causa 2: contenuti inseriti sopra quelli esistenti

Banner per i cookie, avvisi di promozione, barre «scarica l'app» e messaggi di errore aggiunti in cima alla pagina dopo il caricamento spingono giù tutto. Ci sono tre strade:

  • riservare lo spazio fin dall'inizio con un'altezza minima, se il contenuto arriverà sicuramente;
  • mostrare il banner in sovrapposizione, con position: fixed, così non altera il flusso del documento;
  • inserire i contenuti dinamici sotto la parte visibile, non sopra.

Per un banner dei consensi, la sovrapposizione in basso è la scelta più semplice e più stabile.

Causa 3: spazi pubblicitari e widget esterni

Gli annunci e i widget di terze parti hanno dimensioni variabili e arrivano tardi. La pratica corretta è assegnare al contenitore un'altezza minima pari alla dimensione più probabile. Se lo spazio resta vuoto, meglio un riquadro neutro che un collasso improvviso: anche far sparire uno spazio riservato genera uno spostamento.

Causa 4: font web che cambiano le metriche

Quando un font web sostituisce quello di ripiego, lettere più larghe o più alte possono far andare a capo le righe in punti diversi, e i paragrafi si allungano. Il fenomeno si attenua scegliendo un font di ripiego simile e regolandone le metriche con i descrittori di @font-face come size-adjust, ascent-override e descent-override, così che il cambio sia quasi invisibile.

@font-face {
  font-family: "Ripiego Regolato";
  src: local("Arial");
  size-adjust: 104%;
  ascent-override: 92%;
}
body { font-family: "FontDelSito", "Ripiego Regolato", sans-serif; }

I valori esatti si ricavano confrontando i due font; esistono strumenti che li calcolano automaticamente.

Causa 5: animazioni che muovono il layout

Animare top, left, margin o height sposta davvero gli elementi e può generare CLS. Le animazioni realizzate con transform, invece, non modificano il layout e non vengono conteggiate. Uno slider che scorre con transform: translateX() è stabile; uno che cambia margin-left non lo è.

Come trovare gli spostamenti

In DevTools, nel pannello Performance, la traccia «Layout shifts» evidenzia ogni spostamento e gli elementi coinvolti. Esiste anche un'opzione di rendering che colora di blu le aree che si spostano mentre si naviga. Sul campo, la libreria web-vitals con attribuzione riporta il selettore dell'elemento che si è spostato di più, informazione preziosa perché alcuni spostamenti si verificano solo con connessioni lente o in pagine lunghe dove l'utente scorre.

Attenzione a una differenza tra laboratorio e realtà: uno strumento come Lighthouse misura solo il caricamento iniziale, mentre i dati reali includono anche gli spostamenti che avvengono durante lo scorrimento, per esempio quando immagini caricate in modalità lazy non hanno dimensioni. Per questo un buon punteggio in laboratorio non garantisce un buon CLS sul campo.

Una lista di controllo

Elemento Verifica
Immagini width e height sempre presenti
Iframe e video aspect-ratio o altezza riservata
Banner in sovrapposizione o con spazio riservato
Annunci contenitore con altezza minima
Font ripiego con metriche regolate
Animazioni solo transform e opacity

In sintesi

  • Il CLS misura gli spostamenti inattesi; buono fino a 0,1, conta la finestra peggiore.
  • Dimensioni esplicite e aspect-ratio risolvono la maggior parte dei casi.
  • Banner e avvisi vanno in sovrapposizione o in uno spazio già riservato.
  • Font di ripiego regolati riducono i salti al cambio di carattere.
  • Anima con transform e verifica anche con dati reali, non solo in laboratorio.
MM
Marco Marzaduri

Marco Marzaduri si occupa di cybersecurity, informatica forense e sviluppo web. Laureato in informatica, unisce il rigore dell'analisi tecnica all'attenzione per le persone che usano la tecnologia.

Leggi anche