Layout Shift causato dalle transizioni CSS
Scopri come trovare e rimuovere le transizioni CSS che creano layout shift

Perché le transizioni CSS causano i layout shift
I Cumulative Layout Shift causati dalle transizioni CSS si verificano spesso all'inizio della fase di caricamento della pagina. Questi layout shift non si verificano in modo costante, il che li rende difficili da debuggare.
Ultima revisione da parte di Arjen Karel a marzo 2026
Table of Contents!
Il problema transition: all
La causa più comune dei layout shift legati alle transizioni è transition: all. Secondo il capitolo CSS del Web Almanac 2022, il 53% delle pagine utilizza transition: all. Questo significa che ogni modifica delle proprietà viene animata, incluse quelle che influenzano il layout come width, height, margin e padding.
Una transizione CSS ha una proprietà (property), una durata (duration), una funzione di temporizzazione (timing-function) e un ritardo (delay). La sintassi abbreviata (shorthand) è simile a questa:
/* property | duration | timing-function | delay */ transition: margin-right 4s ease-in-out 1s;
Il problema inizia quando gli sviluppatori scrivono transition: all .3s ease invece di specificare l'esatta proprietà che vogliono animare. Durante il caricamento della pagina, un elemento above-the-fold come un menu di navigazione passa dal suo stato iniziale (senza stile) al suo stato finale (con stile o addirittura nascosto). Se la transition property è all, ciò include width, height e persino la visibilità. Il risultato: un layout shift che si verifica solo durante il caricamento ed è quasi impossibile da riprodurre costantemente.
Quali proprietà CSS causano layout shift?
Non tutte le transizioni CSS causano layout shift. Solo le proprietà che modificano la geometria o la posizione di un elemento attivano la fase di layout del browser. Secondo una ricerca di Google, le pagine che animano le proprietà CSS che inducono il layout hanno il 15% di probabilità in meno di superare il CLS. Le pagine che animano margin o border-width hanno un CLS scarso quasi al doppio del tasso normale.
Proprietà che causano layout shift: width, height, margin, padding, top, left, right, bottom, border-width, font-size, display
Proprietà sicure (solo composizione, nessun layout shift): transform, opacity, filter, clip-path
Proprietà sicure (solo disegno, nessun layout shift): background-color, color, box-shadow, outline
Il punto chiave: transform e opacity sono gestiti interamente dal thread del compositor del browser. Non attivano mai il ricalcolo del layout, quindi non contano mai per il CLS. Se devi spostare un elemento, usa transform: translate() invece di top/left. Se devi ridimensionarlo visivamente, usa transform: scale() invece di width/height.
Dai un'occhiata all'esempio qui sotto. Questo dimostra un layout shift causato da transizioni CSS che si verificano durante la fase di caricamento di una pagina. Vedo questo pattern continuamente e trovare e risolvere questo tipo di problemi può essere difficile.
Trova e risolvi le transizioni CSS
Per trovare e risolvere tutti i layout shift causati dalle transizioni CSS dobbiamo eseguire un rapido test. Prima di tutto troviamo tutte le transizioni CSS sulla pagina. Poi controlliamo se qualcuna di esse modifica le proprietà che influenzano il layout. Infine, misuriamo l'impatto della disabilitazione o modifica di quelle transizioni per confermare che stessero causando il CLS.
Suggerimento Core Web Vitals: I Cumulative Layout Shift causati dalle transizioni CSS si verificano spesso all'inizio della fase di caricamento della pagina. Questi layout shift non avvengono costantemente, il che li rende difficili da debuggare. Rallentare la tua rete emulando un dispositivo mobile e disabilitando la cache faciliterà la loro individuazione!
Passaggio 1: Trova le transizioni CSS
Trovare le transizioni CSS può essere fatto manualmente: ispeziona tutti i fogli di stile e cerca la parola 'transition'. Non dovrebbe richiedere più di 10 minuti di lavoro ma esiste un modo migliore! Basta incollare questo snippet nella console e premere invio
(() => {
let nodeTable = [];
let nodeArray = [];
// Get the name of the node
function getName(node) {
const name = node.nodeName;
return node.nodeType === 1
? name.toLowerCase()
: name.toUpperCase().replace(/^#/, '');
}
// Get the selector
const getSelector = (node) => {
let sel = '';
try {
while (node && node.nodeType !== 9) {
const el = node;
const part = el.id
? '#' + el.id
: getName(el) +
(el.classList &&
el.classList.value &&
el.classList.value.trim() &&
el.classList.value.trim().length
? '.' + el.classList.value.trim().replace(/\s+/g, '.')
: '');
if (sel.length + part.length > (100) - 1) return sel || part;
sel = sel ? part + '>' + sel : part;
if (el.id) break;
node = el.parentNode;
}
} catch (err) {
// Do nothing...
}
return sel;
};
const getNodesWithTransition = (node) => {
// Get the computed style
let cs = window.getComputedStyle(node);
let tp = cs['transition-property'];
let td = cs['transition-duration'];
// If there is a transition, add it to the table
if (tp !== '' && tp !== 'none' && td != '0s') {
nodeTable.push({ selector: getSelector(node), transition: cs['transition'] });
nodeArray.push(node);
}
// Recursively call this function for each child node
for (let i = 0; i < node.children.length; i++) {
getNodesWithTransition(node.children[i]);
}
}
// find all transitions
getNodesWithTransition(document.body);
// Display the results in the console
console.log('%cReadable table of selectors and their transitions', 'color: red; font-weight: bold;');
console.table(nodeTable);
console.log('%cNodeList for you to inspect (harder to read but more info)', 'color: red; font-weight: bold;');
console.log(nodeArray);
// styles to temporarity override the transitions
let selectors = nodeTable.map((item) => item.selector).join(', ');
console.log('%cSpecific CSS to disable all transitions on this page', 'color: red; font-weight: bold;');
console.log(`<style>${selectors}{transition-property: none !important;}</style>`);
console.log('%cGlobal CSS to disable all transitions on this page (not suggested on production)', 'color: red; font-weight: bold;');
console.log(`<style>*{transition-property: none !important;}</style>`);
})()
Ti mostrerà una tabella di tutte le transizioni, gli elementi su cui stanno lavorando e maggiori dettagli sulle transizioni.

Per trovare i layout shift, cerca proprietà di transizione come width, height, margin, padding, top, left, display e specialmente all (poiché all include ogni transition property valida).
Passaggio 2: Modifica le transizioni CSS
Lo snippet JavaScript qui sopra mostrerà tutte le transizioni oltre a fornire codice di esempio su come disabilitare tali transizioni. Per scopi di test rapidi ti suggerisco di prendere la strada facile e disabilitare tutte le transizioni con una semplice riga di codice CSS
<style>*{transition-property: none !important;}</style>Ovviamente per gli ambienti live è richiesta un po' più di precisione. Rimuovi con attenzione solo le transition-property non necessarie in base al selettore. Ad esempio, cambia #button{transition: all .2s} in #button{transition: background-color .2s}
Passaggio 3: Misura la variazione del layout shift
transition: all con proprietà specifiche hanno visto migliorare il proprio CLS in media del 40%.
Migliori pratiche per le transizioni
- Specifica sempre la proprietà esatta: Non usare mai
transition: all. Scrivi invecetransition: background-color .2s ease. Questo previene layout shift accidentali da proprietà che non intendevi animare. - Usa transform e opacity per le animazioni: Queste due proprietà sono gestite dal compositor e non attivano mai il layout. Usa
transform: translate()per spostare gli elementi,transform: scale()per ridimensionarli visivamente eopacityper sfumarli. Questo è ciò che raccomanda Google per animazioni ad alte prestazioni. - Imposta dimensioni esplicite sugli elementi animati: Se un elemento deve eseguire una transizione, assicurati che abbia width e height (o un aspect ratio) espliciti prima e dopo la transizione. Questo impedisce al contenuto circostante di spostarsi. Per saperne di più su questo argomento, consulta come risolvere i layout shift causati dalle immagini che si ridimensionano automaticamente.
- Fai attenzione a will-change: La proprietà CSS
will-changedice al browser di prepararsi a un'animazione promuovendo l'elemento a un proprio layer di compositor. Ma comporta dei compromessi: crea un nuovo contesto di stacking (stacking context), aumenta l'utilizzo della memoria GPU e stabilisce un blocco contenitore (containing block) per i discendenti posizionati. Applicala dinamicamente con JavaScript appena prima dell'inizio dell'animazione, e rimuovila quando l'animazione termina. Non lasciarewill-changenel tuo foglio di stile in modo permanente.
Nonostante tutto questo, il Web Almanac 2025 riporta che il 40% delle pagine mobili esegue ancora animazioni non composte (non-composited). La buona notizia: il CLS è il Core Web Vital con il tasso di superamento più alto all'81% su mobile. La cattiva notizia: se il tuo sito rientra nel 19% che fallisce, le transizioni CSS potrebbero essere la causa che non hai ancora controllato.
I write the code, not the report.
I join your team for 1 to 2 sprints. I set up the monitoring and make sure your team keeps the metrics green after I leave.
Get in touch
