Vind en fix Cumulative Layout Shift (CLS)-problemen

Leer hoe je alle Cumulative Layout Shift-problemen vindt en fixt met RUM-data, Chrome DevTools en gerichte CSS- en HTML-fixes.

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-10-26

Vind en fix Cumulative Layout Shift (CLS)-problemen

Deze pagina is onderdeel van onze serie over Cumulative Layout Shift (CLS). CLS meet de visuele stabiliteit van je pagina door onverwachte bewegingen van content bij te houden. Een goede CLS-score ligt onder de 0,1. Scores boven de 0,25 zijn slecht. Ben je nieuw met CLS, begin dan op de CLS-hubpagina voor de formule, drempelwaarden en de werking van session windows.

CLS presteert van alle Core Web Vitals het best. Volgens de 2025 Web Almanac haalt wereldwijd 72% van de websites een voldoende voor CLS. Dat klinkt geweldig, totdat je beseft dat de meeste developers CLS-problemen nooit op hun eigen machine zien. De shifts treden op bij nieuwe bezoekers op een trage verbinding. Controleer je het in DevTools met een opgewarmde cache, dan lijkt alles in orde. Juist dat maakt CLS lastig te debuggen.

Deze gids is gebaseerd op het exacte stappenplan dat ik gebruik bij CLS-consultancy. Eerst CrUX- en RUM-data, valideren in Chrome en daarna de fix schrijven.

Laatst gecontroleerd door Arjen Karel in maart 2026

CLS-TIP: CLS wordt gemeten in session windows, niet als een doorlopend totaal. De browser groepeert layout shifts in sessies (maximaal 5 seconden, met gaten van 1 seconde tussen shifts). Je CLS-score is de slechtste sessie. Eén korte reeks shifts tijdens het laden van de pagina kan al voor een onvoldoende op CLS zorgen, zelfs als de rest van het bezoek perfect stabiel is.

Stap 1: Check CLS in Search Console

Voordat je iets aanpast: controleer eerst of je echt een CLS-probleem hebt. Log in op Google Search Console, ga naar Core Web Vitals en bekijk zowel mobiel als desktop.

Markeert Google URL's met "CLS issue: more than 0.25" of "CLS issue: more than 0.1", dan heb je via het Chrome User Experience Report (CrUX) de bevestiging dat echte gebruikers layout shifts ervaren op je site.

Waar het bij LCP en INP draait om pure rekenkracht en netwerksnelheid, kunnen CLS-problemen specifiek zijn voor een apparaat of schermgrootte. Speelt hetzelfde probleem op mobiel en desktop (afbeeldingen zonder afmetingen, font swaps, geïnjecteerde content), dan kan desktop door het grotere schermformaat een veel hogere CLS-waarde rapporteren (omdat een groter deel van de zichtbare viewport kan worden geraakt). Search Console groepeert URL's: je ziet wel welke paginatypes problemen hebben, maar niet welke elementen verschuiven. Daar heb je Real User Monitoring voor nodig.

Google Search Console showing INP issue: longer than 200ms (mobile) with 2.07M affected URLs

Stap 2: Identificeer CLS-problemen met RUM-data

Search Console bevestigt dat het probleem bestaat, maar geeft je amper aanknopingspunten. Je moet weten welke elementen verschuiven, op welke pagina's en onder welke omstandigheden. Daar heb je een RUM-tool voor nodig.

Ik heb CoreDash gebouwd om precies deze vragen te beantwoorden. Je voegt één script-tag toe en de tool verzamelt CLS-attributiedata van elke echte bezoeker. Het belangrijkste datapunt bij het debuggen van CLS is het verschuivende element: de DOM-node die echt bewoog. Zonder die informatie debug je blind.

Vind verschuivende elementen

Begin met je CLS-data gegroepeerd op element. Ga in CoreDash naar de CLS-pagina en bekijk de tabel gesorteerd op "CLS by Element". Dit toont welke elementen de meeste layout shift veroorzaken bij al je bezoekers. Klik op de grootste boosdoener om alle statistieken te filteren op pagina's waar dat element verschoof.

CoreDash showing CLS scores broken down by shifting element.

Bekijk welke pagina's geraakt worden

Heb je gefilterd op het verschuivende element met de meeste impact, bekijk dan de uitsplitsing per URL. CLS-problemen kunnen site-wide zijn of binnen één template spelen. Nu weten we of de CLS zich concentreert op specifieke paginatypes: productpagina's met fotogalerijen, blogposts met ad slots of landingspagina's met hero-animaties. Weet je welke pagina's zakken, dan weet je waar je focus moet liggen.

Check nieuwe versus terugkerende bezoekers

Dit is nog zo'n snelle check die ik altijd doe, en het maakt meer uit dan de meeste mensen denken. Font-swap CLS gebeurt alleen wanneer het font niet gecachet is. CLS door width: auto op een afbeelding gebeurt alleen wanneer de afbeelding niet in de browsercache zit. Is je CLS veel slechter bij nieuwe bezoekers, dan heb je te maken met een shift die afhangt van caching. Die zie je als developer op je eigen machine nooit, tenzij je de cache uitschakelt (tip: zet je Chrome-cache altijd uit ... maar dat is weer een ander verhaal).

Check apparaattypes en viewport-afmetingen

CLS vertoont vaak een ander patroon tussen mobiel en desktop dan LCP en INP. Responsive layouts kunnen shifts veroorzaken die alleen bij specifieke viewport-breedtes en -hoogtes opduiken. Een ad slot die op desktop problemen gaf, staat op mobiel misschien niet eens in de viewport. Een navigatiemenu animeert op kleinere breakpoints wellicht anders. Groepeer je CLS-data op apparaattype om te weten waar ze optreden.

Stap 3: Debug CLS met Chrome

Je RUM-data heeft laten zien welke elementen verschuiven en waarom. Reproduceer het probleem nu lokaal en achterhaal de oorzaak.

Gebruik de Core Web Vitals Visualizer

De snelste manier om layout shifts te zien is met de Chrome-extensie Core Web Vitals Visualizer. Laad de pagina, klik op het extensie-icoon en reload. Elke layout shift wordt gemarkeerd met een gekleurde overlay die precies toont wat er bewoog en met hoeveel. Dit is mijn eerste stap voordat ik het Performance-paneel open, omdat het meteen een visueel antwoord geeft.

Core Web Vitals Visualizer showing layout shifts highlighted on the page.

Simuleer de omstandigheden in Chrome en check de network screenshots

Met een warme cache zijn CLS-problemen vaak onzichtbaar. Open DevTools, schakel de cache uit in het Network-tabblad en zet throttling op "Slow 4G" (mijn favoriet, want hiermee zie je CLS veroorzaakt door race conditions). Klik nu op het tandwielicoon en schakel caching uit (terwijl DevTools open staat). Zo simuleer je de omstandigheden van nieuwe bezoekers. Ga naar het Network-tabblad en zet screenshots aan. Reload nu de pagina en let op verschuivingen.

Chrome DevTools Network tab with screenshots showing request timing for CLS analysis

Gebruik het Performance-paneel in Chrome

De meeste layout shifts zie je zo als je weet waar je op moet letten, maar soms ontglippen ze je. Dan open je Chrome DevTools (Ctrl+Shift+I) en ga je naar het Performance-paneel voor gedetailleerd debugwerk. Druk op Ctrl+Shift+E om te reloaden en op te nemen. Scroll nadat de pagina geladen is een paar keer op en neer. Stop de opname.

Zoek de track "Layout Shifts". Elke shift verschijnt als een gekleurd blok. Klik op een shift om het volgende te zien:

  • De verschuivende node: het DOM-element dat bewoog
  • De shift-score: impact fraction vermenigvuldigd met distance fraction
  • hadRecentInput: of gebruikersinput voorafging aan de shift (klikken en tikken krijgen een respijtperiode van 500 ms, maar scrollen niet)

Let goed op wanneer de shifts plaatsvinden. Shifts tijdens het laden van de pagina wijzen op afbeeldingen zonder afmetingen, font swaps of CSS-transitions. Shifts tijdens het scrollen wijzen op scroll-triggered animaties die layout-properties gebruiken.

Chrome Performance panel showing layout shift entries during scrolling.

Snelle test: schakel alle transitions uit

CSS-transitions die layout-properties animeren zijn een verraderlijke oorzaak van CLS: ze verschuiven alleen tijdens de laadfase en zijn lastig te reproduceren. Plak dit snippet in de console, doe een hard reload met uitgeschakelde cache en vergelijk de CLS:

document.head.insertAdjacentHTML('beforeend',
  '<style>*{transition-property:none!important}</style>');

Daalt je CLS na het uitschakelen van transitions, dan heb je de oorzaak gevonden. Gebruik de gids voor het debuggen van CSS-transitions om de specifieke transitions te vinden die hiervoor zorgen.

CLS meten met de Layout Instability API

De Layout Instability API geeft je in JavaScript direct toegang tot elke layout shift. Onder de motorkap gebruiken RUM-tools exact deze API:

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (!entry.hadRecentInput) {
      console.log('Layout shift:', {
        value: entry.value,
        sources: entry.sources?.map(s => ({
          node: s.node,
          previousRect: s.previousRect,
          currentRect: s.currentRect
        }))
      });
    }
  }
});
observer.observe({ type: 'layout-shift', buffered: true });

De array sources toont welke elementen bewogen. hadRecentInput filtert verwachte verschuivingen door klikken en tikken weg. Gebruik voor metingen in productie CoreDash of een andere RUM-tool.

Stap 4: Fix CLS-problemen

Je weet welke elementen verschuiven en waarom. Tijd om ze te fixen. CLS heeft geen opeenvolgende fases zoals LCP. In plaats daarvan vallen layout shifts uiteen in duidelijke categorieën van oorzaken. Dit zijn de meest voorkomende, op volgorde van hoe vaak ik ze tegenkom tijdens audits.

1. Afbeeldingen, video's en iframes zonder afmetingen

Dit is de nummer één oorzaak van CLS op het web. Volgens de 2025 Web Almanac heeft 62% van de mobiele pagina's minstens één afbeelding zonder afmetingen. De fix: voeg altijd width- en height-attributen toe aan <img>-, <video>- en <iframe>-tags.

<img src="hero.jpg" width="800" height="450" alt="Description">

<style>
img {
    height: auto;
    max-width: 100%;
}
</style>

Kijk uit met width: auto in je CSS. Deze ene declaratie overschrijft de aspect ratio-berekening van de browser en veroorzaakt alsnog layout shifts, zelfs als je width en height hebt ingesteld in de HTML. Ik heb dit op tientallen sites gezien. De developer deed alles goed in de markup, maar een globale CSS-regel zoals img { width: auto; height: auto; max-width: 100%; } maakte dat allemaal ongedaan. Bekijk voor de volledige uitleg layout shift door auto-sizing afbeeldingen fixen. Voor een complete gids over alle CLS-oorzaken rond afbeeldingen en media (video's, iframes, art direction, responsive afbeeldingen, lazy loading, placeholders), zie Hoe afbeeldingen en media layout shift veroorzaken.

2. Web font swaps

Zodra een web font laadt en het fallback-font vervangt, veroorzaakt het verschil in afmetingen een layout shift. Uit de 2025 Web Almanac blijkt dat slechts 11% van de pagina's web fonts preloadt. Dat betekent dat het overgrote deel van de websites kwetsbaar is voor font-swap CLS.

De fix bestaat uit twee delen. Zorg er eerst voor dat het fallback-font aansluit op de afmetingen van het web font via metric overrides:

<style>
@font-face {
    font-family: 'My Font Fallback';
    src: local('Arial');
    size-adjust: 105.2%;
    ascent-override: 93%;
    descent-override: 24%;
    line-gap-override: 0%;
}

@font-face {
    font-family: 'My Font';
    src: url('/fonts/myfont.woff2') format('woff2');
    font-display: swap;
}

body {
    font-family: 'My Font', 'My Font Fallback', sans-serif;
}
</style>

Gebruik een Fallback Font Generator om de juiste override-waarden voor je font-combinatie te berekenen. Versnel daarnaast de levering: host je fonts zelf, preload je kritieke font-bestand en gebruik WOFF2 met subsetting. Zie voor een complete strategie responsive web fonts laden en zorgen dat tekst zichtbaar blijft tijdens het laden van web fonts.

3. CSS-animaties en -transitions

Volgens de 2025 Web Almanac draait op 40% van de mobiele pagina's non-composited animaties. Die animeren properties zoals width, height, top, left, margin en padding, wat bij elk frame een herberekening van de layout triggert.

De grootste boosdoener is transition: all. Schrijft een developer transition: all .3s ease, dan wordt elke verandering van een property geanimeerd, inclusief layout-properties. Tijdens het laden van de pagina produceren elementen die overgaan van hun unstyled naar gestylde state layout shifts die af en toe optreden en nauwelijks consistent te reproduceren zijn. Dit patroon kom ik voortdurend tegen.

De fix: vervang properties die een layout triggeren door composited properties.

  • Gebruik transform: translateY() in plaats van top/bottom
  • Gebruik transform: translateX() in plaats van left/right
  • Gebruik transform: scale() in plaats van width/height
  • Gebruik opacity in plaats van visibility gecombineerd met hoogteveranderingen
  • Gebruik nooit transition: all. Specificeer de exacte property: transition: background-color .2s ease

transform en opacity draaien volledig op de compositor thread en triggeren nooit een layout. Bekijk voor het complete debugproces layout shift veroorzaakt door CSS-transitions.

4. Advertenties, embeds en dynamisch geïnjecteerde content

Advertenties laden laat en drukken content naar beneden. Cookiebanners verschijnen en verschuiven de pagina. AJAX-requests injecteren nieuwe content zonder eerst ruimte te reserveren. Dit is allemaal hetzelfde probleem: er verschijnt iets op de pagina waar de browser tijdens het renderen nog niets van wist.

De fix voor dit alles is ruimte reserveren. Stel voor ad slots een min-height in die past bij het verwachte advertentieformaat:

<style>
.ad-slot {
    min-height: 250px;
    contain: layout style;
}
@media (min-width: 600px) {
    .ad-slot { min-height: 90px; }
}
</style>

De declaratie contain: layout style isoleert de ad-container van de rest van de pagina. Gebruik voor cookiebanners position: fixed voor een overlay in plaats van content omlaag te duwen. Reserveer voor AJAX-content ruimte met min-height. Een exacte schatting is niet nodig: een verschil van 50px levert veel minder CLS op dan een shift van 400px zonder gereserveerde ruimte.

Gebruik voor third-party embeds zoals YouTube, Google Maps en chat-widgets het facade pattern: toon een statische placeholder en laad de echte embed pas zodra de bezoeker ermee interacteert. Nul CLS, nul verspilde resources.

5. Scroll-triggered layout shifts

Dit is de CLS-oorzaak die Lighthouse nooit ontdekt. Lighthouse scrollt niet over de pagina, waardoor scroll-triggered layout shifts compleet onzichtbaar zijn in lab data. De enige manier om ze te vinden is met RUM-data of door handmatig te scrollen terwijl je een trace opneemt in het Performance-paneel.

Het bekendste voorbeeld is een hide-on-scroll header die de property top animeert. Dit is wat de meeste developers niet weten: scrollen is geen uitsluitende input in de Layout Instability-specificatie. Klikken en tikken krijgen een respijtperiode van 500 ms. Scrollen niet. Elke layout shift die door scrollen getriggerd wordt, telt mee voor je CLS-score.

De fix: gebruik transform: translateY() in plaats van top voor elke scroll-triggered animatie. Hetzelfde geldt voor parallax-effecten, meekrimpende navigatiebalken en voortgangsbalken gekoppeld aan scrollen. Beweegt het bij het scrollen, animeer het dan met transform. Bekijk voor het complete stappenplan inclusief video-voorbeelden hoe scroll-triggered animaties CLS veroorzaken.

Snelle fix-checklist

CLS-oorzaak Hoe ontdek je het Fix
Afbeeldingen/video's zonder afmetingen Lighthouse-audit "unsized images" Voeg width en height toe; verwijder width: auto uit de CSS
Web font swaps RUM: CLS alleen slechter bij het eerste bezoek Font metric overrides; preload WOFF2; host fonts zelf
CSS-transitions Console-snippet om alle transitions te tonen Vervang transition: all door specifieke properties; gebruik transform/opacity
Laat ladende advertenties RUM-attributie toont ad-containerelementen min-height op ad slots; contain: layout style
Cookiebanners CLS-piek bij eerste bezoek; banner zichtbaar in attributiedata Gebruik een position: fixed overlay in plaats van content weg te drukken
Scroll-animaties Performance-trace tijdens scrollen; field-CLS > lab-CLS Vervang top/left/height door transform

Gerelateerde handleidingen

Voor een compleet overzicht van alle Core Web Vitals ga je naar de Core Web Vitals-hub, of gebruik de Ultimate Core Web Vitals Checklist om je hele site te auditen.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

Arjen Karel

Een snellere site nodig?

Ik ben Arjen en ik maak al 17 jaar trage sites snel. Loop je tegen iets aan dat je zelf niet opgelost krijgt? Stuur me je URL, dan praten we even.

Stuur me je URL
Arjen Karel
Arjen Karel, Web performance consultant sinds 2009

Waarom werkt onze fix niet?

Soms serveert het CDN nog de oude HTML, of de fix zit in het desktop-template terwijl mobiel een ander template gebruikt. Stuur me je URL en het probleem, dan stuur ik je een paar momenten. Ik bekijk eerst je field data, daarna besteden we een uur aan je site, en binnen een dag heb je mijn notities op schrift. €350 excl. btw.

Stuur me je URL

Geen developer om de fix te bouwen? Ik doe het werk zelf, op een kopie van je site.

Vind en fix Cumulative Layout Shift (CLS)-problemen Core Web Vitals Vind en fix Cumulative Layout Shift (CLS)-problemen