Layout Shift veroorzaakt door CSS transitions
Leer hoe je CSS transitions die layout shifts veroorzaken kunt vinden en verwijderen

Waarom CSS transitions layout shifts veroorzaken
Cumulative Layout Shifts veroorzaakt door CSS transitions treden vaak vroeg op tijdens de laadfase van de pagina. Deze layout shifts gebeuren niet consistent, wat ze lastig te debuggen maakt.
Laatst beoordeeld door Arjen Karel in maart 2026
Table of Contents!
Het transition: all probleem
De meest voorkomende oorzaak van transition-gerelateerde layout shifts is transition: all. Volgens het CSS-hoofdstuk van de Web Almanac 2022 gebruikt 53% van de pagina's transition: all. Dat betekent dat elke property-wijziging wordt geanimeerd, inclusief degene die de layout beïnvloeden, zoals width, height, margin en padding.
Een CSS transition heeft een property, duration, timing-function en een delay. De steno (shorthand) ziet er zo uit:
/* property | duration | timing-function | delay */ transition: margin-right 4s ease-in-out 1s;
Het probleem begint wanneer developers transition: all .3s ease schrijven in plaats van de exacte property op te geven die ze willen animeren. Tijdens het laden van de pagina gaat een above-the-fold element, zoals een navigatiemenu, over van de initiële (ongestijlde) status naar de uiteindelijke (gestijlde of zelfs verborgen) status. Als de transition property all is, omvat dit width, height en zelfs visibility. Het resultaat: een layout shift die alleen tijdens het laden plaatsvindt en bijna onmogelijk consistent te reproduceren is.
Welke CSS properties veroorzaken layout shift?
Niet alle CSS transitions veroorzaken layout shifts. Alleen properties die de geometrie of positie van een element veranderen, triggeren de layout-stap van de browser. Volgens onderzoek van Google hebben pagina's die layout-inducerende CSS properties animeren 15% minder kans om voor CLS te slagen. Pagina's die margin of border-width animeren, hebben bijna twee keer zo vaak een slechte CLS.
Properties die layout shift veroorzaken: width, height, margin, padding, top, left, right, bottom, border-width, font-size, display
Veilige properties (alleen composite, geen layout shift): transform, opacity, filter, clip-path
Veilige properties (alleen paint, geen layout shift): background-color, color, box-shadow, outline
Het belangrijkste inzicht: transform en opacity worden volledig afgehandeld door de compositor-thread van de browser. Ze triggeren nooit een herberekening van de layout, dus ze tellen nooit mee voor CLS. Als je een element moet verplaatsen, gebruik dan transform: translate() in plaats van top/left. Als je de visuele grootte wilt aanpassen, gebruik dan transform: scale() in plaats van width/height.
Bekijk het onderstaande voorbeeld. Dit demonstreert een layout shift veroorzaakt door CSS transitions die optreden tijdens de laadfase van een pagina. Ik zie dit patroon constant, en het vinden en oplossen van dit soort problemen kan lastig zijn.
Vind en fix CSS transitions
Om alle layout shifts veroorzaakt door CSS transitions te vinden en op te lossen, moeten we een snelle test uitvoeren. Eerst zoeken we alle CSS transitions op de pagina. Vervolgens controleren we of een van deze transitions layout-beïnvloedende properties wijzigt. Tot slot meten we de impact van het uitschakelen of aanpassen van die transitions om te bevestigen dat ze CLS veroorzaakten.
Core Web Vitals tip: Cumulative Layout Shifts die worden veroorzaakt door CSS transitions, treden vaak vroeg op tijdens de laadfase van de pagina. Deze layout shifts gebeuren niet consistent, wat ze lastig te debuggen maakt. Het vertragen van je netwerk door een mobiel apparaat te emuleren en je cache uit te schakelen, maakt het vinden ervan makkelijker!
Stap 1: Vind CSS transitions
Het vinden van CSS transitions kan handmatig worden gedaan: inspecteer alle stylesheets en zoek naar het woord 'transition'. Dat zou niet meer dan 10 minuten werk moeten zijn, maar er is een betere manier! Plak deze snippet in de console en druk op enter.
(() => {
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>`);
})()
Het toont je een tabel met alle transitions, de elementen waarop ze werken en meer details over de transitions.

Om layout shifts te vinden, zoek je naar transition properties zoals width, height, margin, padding, top, left, display en vooral all (aangezien all elke geldige transition property omvat).
Stap 2: Pas CSS transitions aan
De bovenstaande JavaScript snippet toont alle transitions en geeft voorbeeldcode om deze uit te schakelen. Voor snelle testdoeleinden raad ik aan de makkelijke weg te kiezen en alle transitions uit te schakelen met één simpele regel CSS-code:
<style>*{transition-property: none !important;}</style>Natuurlijk is voor live-omgevingen iets meer finesse vereist. Verwijder zorgvuldig alleen onnodige transition-properties per selector. Verander bijvoorbeeld #button{transition: all .2s} in #button{transition: background-color .2s}.
Stap 3: Meet de verandering in layout shift
transition: all vervingen door specifieke properties hun CLS gemiddeld met 40% verbeteren.
Transition best practices
- Specificeer altijd de exacte property: Gebruik nooit
transition: all. Schrijf in plaats daarvantransition: background-color .2s ease. Dit voorkomt onbedoelde layout shifts door properties die je niet wilde animeren. - Gebruik transform en opacity voor animaties: Deze twee properties worden afgehandeld door de compositor en triggeren nooit een layout. Gebruik
transform: translate()om elementen te verplaatsen,transform: scale()om hun visuele grootte aan te passen, enopacityom ze te laten infaden of uitfaden. Dit is wat Google aanbeveelt voor high-performance animaties. - Stel expliciete afmetingen in op geanimeerde elementen: Als een element een transition nodig heeft, zorg er dan voor dat het een expliciete width en height (of een aspect-ratio) heeft voor en na de transition. Dit voorkomt dat omliggende content verschuift. Voor meer informatie hierover, zie layout shifts oplossen die worden veroorzaakt door auto-sizing afbeeldingen.
- Wees voorzichtig met will-change: De CSS property
will-changevertelt de browser om zich voor te bereiden op een animatie door het element naar een eigen compositor-laag te promoveren. Maar er zijn trade-offs: het creëert een nieuwe stacking context, verhoogt het GPU-geheugengebruik en vestigt een containing block voor gepositioneerde descendants. Pas het dynamisch toe met JavaScript net voordat de animatie begint, en verwijder het wanneer de animatie eindigt. Laatwill-changeniet permanent in je stylesheet staan.
Ondanks dit alles meldt de Web Almanac 2025 dat 40% van de mobiele pagina's nog steeds niet-gecomposited animaties uitvoert. Het goede nieuws: CLS is de Core Web Vital met het hoogste slagingspercentage van 81% op mobiel. Het slechte nieuws: als jouw site in de falende 19% zit, zijn CSS transitions mogelijk de oorzaak die je nog niet hebt gecontroleerd.
Search Console flagged your site?
I deliver a prioritized fix list backed by field data. Not a 50 page PDF.
Request audit
