Przejdź do treści
ARDURA Lab
ARDURA Lab
·7 min

CLS (Cumulative Layout Shift) — jak naprawić w 2026

MG
Marcin Godula

CEO & Founder, ARDURA Lab

Specjalista SEO, GEO i web development z ponad 15-letnim doświadczeniem. Pomaga firmom B2B budować widoczność w wyszukiwarkach klasycznych i AI.

CLS (Cumulative Layout Shift) to Core Web Vital mierzące visual stability strony — jak bardzo elementy „skaczą" podczas ładowania. Cel <0.1. Wysokie CLS = frustrated users clickujący wrong elements + ranking penalty. W 2026 dobrze zoptymalizowane CLS jest często differentiator między top 3 a top 10 dla competitive queries.

TL;DR — CLS

MetricDetale
Co mierzyVisual stability — element movement during load
GraniceGood <0.1, NI 0.1-0.25, Poor >0.25
Główne przyczynyBrak dimensions, ads, font swap, dynamic content
Quick fix #1Width + height na wszystkich obrazach
Quick fix #2Reserve space dla ads + dynamic content
Quick fix #3Font-display: optional or fallback
ToolsDevTools Performance, PageSpeed Insights, Web Vitals

Czym jest CLS?

Cumulative Layout Shift mierzy unexpected layout shifts during page load. Każdy shift dostaje score na podstawie:

  • Impact fraction — jak bardzo viewport affected
  • Distance fraction — jak daleko element się przesunął

CLS = sum wszystkich layout shifts w session.

Granice

  • Good: <0.1 (passing)
  • Needs Improvement: 0.1-0.25
  • Poor: >0.25

Dlaczego CLS ma znaczenie

  • UX issue — user clicks button → button przeskakuje → clicks wrong thing
  • Trust issue — site czuje się broken / amateur
  • Ranking factor — Core Web Vitals signal
  • Conversion impact — frustrated users abandon

Główne przyczyny CLS

1. Obrazy bez dimensions

<!-- BAD — browser nie wie size, ładowanie shifts layout -->
<img src="image.jpg" alt="..." />

<!-- GOOD — browser reserves space -->
<img src="image.jpg" alt="..." width="1200" height="630" />

Fix: zawsze podaj width + height. Browser kalkuluje aspect ratio i reserves space.

2. Ads injection

Ads pojawiające się po scroll injectują into existing layout, pushing content down:

<!-- BAD — ad placeholder bez height -->
<div class="ad-slot">
  <!-- Ad loads here, pushes content -->
</div>

<!-- GOOD — reserved space -->
<div class="ad-slot" style="min-height: 250px">
  <!-- Ad loads, no shift -->
</div>

Fix: reserve minimum height dla każdego ad slot.

3. Web fonts loading

FOUT (Flash of Unstyled Text) → custom font loads → text reflows → layout shifts.

/* BAD - block render until font loaded */
@font-face {
  font-family: 'CustomFont';
  src: url('/font.woff2');
}

/* GOOD - prevent shift */
@font-face {
  font-family: 'CustomFont';
  src: url('/font.woff2');
  font-display: optional;  /* nie blokuje, nie shifts */
}

/* Alternative - swap fast */
@font-face {
  font-display: swap;  /* shows fallback, swap when loaded */
  size-adjust: 95%;  /* fallback similar size do custom */
}

Fix: font-display: optional (best for CLS) lub swap z size-adjust.

4. Dynamic content injection

Cookie banners, popups, chat widgets pojawiające się po opóźnieniu push content:

/* GOOD - cookie banner z fixed positioning */
.cookie-banner {
  position: fixed;
  bottom: 0;
  /* nie shifts main layout */
}

Fix: dynamic content jako overlay, nie inline.

5. Embed iframes

YouTube, Twitter, social embeds — często bez aspect ratio:

<!-- BAD - height not set -->
<iframe src="https://youtube.com/..." />

<!-- GOOD - aspect ratio container -->
<div style="aspect-ratio: 16/9;">
  <iframe src="https://youtube.com/..." style="width: 100%; height: 100%;" />
</div>

Fix: wrap embed w aspect-ratio container.

6. Lazy-loaded sections

Content appearing on scroll może shifts layout if not properly positioned.

<!-- BAD - lazy section appears, pushes below -->
<section class="lazy-load">
  <!-- Content loads here -->
</section>

<!-- GOOD - reserved height -->
<section class="lazy-load" style="min-height: 600px">
  <!-- Content loads, no shift -->
</section>

Debugging CLS

Chrome DevTools

  1. F12 → Performance tab
  2. Settings → Show layout shifts
  3. Click record
  4. Refresh page
  5. Stop recording
  6. Layout shifts highlighted (red rectangles)

PageSpeed Insights

pagespeed.web.dev → CLS section pokazuje:

  • CLS score
  • Largest contentful shifts
  • Recommendations

Web Vitals Chrome Extension

Real-time CLS w toolbar. Test live as you browse.

Lighthouse

Lighthouse CI z CLS threshold w pipeline (fail builds <0.1).

Fixes per common scenario

Scenario 1: Hero image LCP causing CLS

<!-- Without width/height, image loads → shifts everything below -->
<img src="hero.jpg" alt="Hero" />

<!-- Fix -->
<img src="hero.jpg" alt="Hero" width="1920" height="800" 
     style="width: 100%; height: auto;" />

CSS keeps responsive size while preserving aspect ratio.

Scenario 2: WordPress dynamic widgets

WordPress widgets często load asynchronously:

  • Newsletter signup widget loads → shifts
  • Related posts plugin → shifts

Fix:

.widget-area {
  min-height: 400px; /* reserved */
}

Scenario 3: React hydration shift

React SSR + hydration sometimes shifts layout:

  • Server renders A
  • Client hydrates → component re-renders B
  • Shift!

Fix:

  • Match SSR + CSR (avoid client-only logic w initial render)
  • Use suppressHydrationWarning carefully
  • Skeleton screens dla loading states

Scenario 4: Video embeds (YouTube, Vimeo)

<!-- Aspect-ratio container -->
<div style="aspect-ratio: 16/9; max-width: 100%;">
  <iframe src="https://youtube.com/embed/..." 
          style="width: 100%; height: 100%; border: 0;" />
</div>

Scenario 5: Google Ads / banner ads

Reserve dla ad slots:

<div class="ad-slot" style="min-height: 250px; min-width: 300px;">
  <!-- AdSense, GAM, etc. -->
</div>

Use Google Ad Manager fixed-size slots zamiast responsive.

CSS techniques

aspect-ratio (modern, recommended)

.image-container {
  aspect-ratio: 16/9;
  width: 100%;
}

Padding-bottom hack (legacy)

.image-container {
  position: relative;
  padding-bottom: 56.25%; /* 16:9 aspect */
}
.image-container img {
  position: absolute;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

Min-height reserves

.section-with-dynamic-content {
  min-height: 400px;
}

Mobile vs desktop CLS

Mobile typowo wyższe CLS:

  • Smaller viewport — same shift bigger %
  • Slower fonts/images load
  • Touch interactions more shift-sensitive

Test priority: mobile-first dla CLS optimization.

CLS dla różnych frameworków

Next.js / React

  • <Image /> component automatic dimensions
  • fontFamily z next/font — automatic font-display swap
  • next/script z lazyOnload

Astro

  • Built-in image optimization
  • Component islands minimize hydration shift

WordPress

  • Lazy load images native (5.5+)
  • Plugin: WP Rocket — lazy + fixes
  • Theme z proper image dimensions critical

Vanilla HTML

  • Manual width/height
  • CSS aspect-ratio
  • Font-display: optional/swap

Najczęstsze błędy

  1. Brak width/height na obrazach — top przyczyna
  2. Custom fonts bez font-display — FOUT shifts
  3. Ads bez reserved space
  4. Lazy-loaded content bez height
  5. Dynamic JS injecting content synchronously
  6. YouTube embeds bez aspect-ratio
  7. Cookie banner inline zamiast overlay
  8. Test tylko na fast WiFi — slow connections show CLS more

CLS optimization checklist

  • Wszystkie obrazy mają width + height
  • Font-display: optional / swap
  • Ads slots mają min-height
  • Iframes z aspect-ratio
  • Cookie banner = overlay (fixed position)
  • Lazy-loaded sections z reserved space
  • Test mobile + desktop
  • Test slow 3G connection
  • CLS w real user monitoring (Web Vitals JS)
  • CLS w CI/CD pipeline (fail <0.1)

Mierzenie + monitoring

Real User Monitoring (RUM)

import {onCLS} from 'web-vitals';

onCLS(metric => {
  console.log('CLS:', metric.value);
  // Send to analytics
  gtag('event', 'web_vitals', {
    name: 'CLS',
    value: metric.value,
  });
});

Track real users, identify problem pages.

CrUX data

CrUX Compare — CLS vs konkurencja.

Podsumowanie

CLS 2026:

  1. Cel <0.1 dla passing CWV
  2. Width + height na wszystkich obrazach
  3. Font-display: optional lub swap z size-adjust
  4. Reserve space dla ads + dynamic content
  5. Aspect-ratio CSS dla embeds
  6. Test mobile primarily
  7. RUM + CI dla continuous monitoring

CLS to often najłatwiejszy CWV do fix — większość issues quick wins (add dimensions, font-display, reserved space). Inwestycja kilku godzin = passing Page Experience score.

Audyt Core Web Vitals + CLS — sprawdzimy obecne CLS + roadmap fixes.

Potrzebujesz pomocy z tym tematem?

Zamów bezpłatny audyt i dowiedz się, jak możemy pomóc Twojej firmie rosnąć w internecie.

Bezpłatna wycena