Layout Shift veroorzaakt door CSS transities
Leer hoe je CSS transities die layout shifts creëren kunt vinden en verwijderen

Waarom CSS transities layout shifts veroorzaken
Cumulative Layout Shifts veroorzaakt door CSS transities treden vaak vroeg op tijdens de laadfase (loading phase) van de pagina. Deze layout shifts gebeuren niet consistent, wat ze moeilijk te debuggen maakt.
Laatst beoordeeld door Arjen Karel in maart 2026
Table of Contents!
Het transition: all probleem
De meest voorkomende oorzaak van transitie-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 de wijzigingen die invloed hebben op de lay-out, zoals width, height, margin en padding.
Een CSS transitie heeft een property, duration, timing-function en een delay. De shorthand ziet er als volgt 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 zijn initiële (ongestileerde) staat naar zijn uiteindelijke (gestileerde of zelfs verborgen) staat. Als de transition property all is, omvat dit breedte, hoogte en zelfs zichtbaarheid. Het resultaat: een layout shift die alleen plaatsvindt tijdens het laden en bijna onmogelijk consistent te reproduceren is.
Welke CSS properties veroorzaken layout shift?
Niet alle CSS transities veroorzaken layout shifts. Alleen properties die de geometrie of positie van een element veranderen, activeren de lay-outstap (layout step) van de browser. Volgens onderzoek van Google hebben pagina's die lay-outinducerende CSS properties animeren 15% minder kans om te slagen voor CLS. Pagina's die margin of border-width animeren, hebben een slechte CLS met bijna het dubbele van het normale percentage.
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 activeren nooit herberekening van de lay-out, dus ze tellen nooit mee voor de 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 transities 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.
CSS transities vinden en oplossen
Om alle layout shifts veroorzaakt door CSS transities te vinden en op te lossen, moeten we een snelle test uitvoeren. Eerst zoeken we alle CSS transities op de pagina. Vervolgens controleren we of een van hen de lay-out beïnvloedende properties wijzigt. Ten slotte meten we de impact van het uitschakelen of aanpassen van die transities om te bevestigen dat ze de CLS veroorzaakten.
Core Web Vitals tip: Cumulative Layout Shifts die worden veroorzaakt door CSS transities, treden vaak vroeg op tijdens de laadfase van de pagina. Deze layout shifts gebeuren niet consistent, wat ze moeilijk te debuggen maakt. Je netwerk vertragen door een mobiel apparaat te emuleren en je cache uit te schakelen, maakt het vinden ervan makkelijker!
Stap 1: Vind CSS transities
Het vinden van CSS transities 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 gewoon dit fragment 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 zal je een tabel laten zien van alle transities, de elementen waarop ze werken en meer details over de transities.

Om layout shifts te vinden, zoek je naar transition properties zoals width, height, margin, padding, top, left, display en in het bijzonder all (aangezien all elke geldige transition property omvat).
Stap 2: Wijzig CSS transities
Het bovenstaande JavaScript-fragment zal alle transities tonen en ook voorbeeldcode geven over hoe je deze transities kunt uitschakelen. Voor snelle testdoeleinden raad ik je aan om de makkelijke weg te kiezen en alle transities uit te schakelen met één simpele regel CSS code
<style>*{transition-property: none !important;}</style>Voor live omgevingen is natuurlijk iets meer finesse vereist. Verwijder voorzichtig alleen onnodige transition-properties op per-selector basis. 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 [CD:placeholder]% verbeteren.
Best practices voor transities
- 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 van plan was te animeren. - Gebruik transform en opacity voor animaties: Deze twee properties worden afgehandeld door de compositor en activeren nooit de lay-out. Gebruik
transform: translate()om elementen te verplaatsen,transform: scale()om ze visueel te vergroten of te verkleinen, enopacityom ze te laten vervagen. Dit is wat Google aanbeveelt voor snelle animaties. - Stel expliciete dimensies in op geanimeerde elementen: Als een element een transitie nodig heeft, zorg er dan voor dat het een expliciete breedte en hoogte (of een aspect ratio) heeft voor en na de transitie. Dit voorkomt dat omliggende content verschuift. Voor meer informatie hierover, zie layout shifts oplossen die worden veroorzaakt door automatisch schalende 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 (layer) te bevorderen. Maar er zitten nadelen aan: het creëert een nieuwe stacking context, verhoogt het GPU-geheugengebruik en stelt een containing block in voor gepositioneerde nakomelingen (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 non-composited animaties uitvoert. Het goede nieuws: CLS is de Core Web Vital met het hoogste slagingspercentage van 81% op mobiel. Het slechte nieuws: als je site bij de falende 19% hoort, kunnen CSS transities de oorzaak zijn die je nog niet hebt gecontroleerd.
Search Console flagged your site?
When Google flags your Core Web Vitals you need a clear diagnosis fast. I deliver a prioritized fix list within 48 hours.
Request Urgent Audit
