Jak opravit CLS: 8 technik pro stabilní layout v roce 2026

Naučte se opravit CLS skóre 8 ověřenými technikami pro rok 2026. Rezervace rozměrů obrázků, fallback fonty se size-adjust, ad slots a měření v produkci s ukázkami kódu.

Jak opravit CLS: Stabilní layout (2026)

Aktualizováno: 6. června 2026

CLS (Cumulative Layout Shift) opravíte tak, že rezervujete místo pro každý prvek, který se načítá asynchronně: obrázky, reklamy, vložená videa i webové fonty. Konkrétně nastavte atributy width a height u obrázků, použijte CSS vlastnost aspect-ratio u responzivních kontejnerů, deklarujte size-adjust u fallback fontů a vyhněte se vkládání obsahu nad stávající prvky po načtení stránky. V roce 2026 platí, že dobré CLS skóre je pod 0,1, kdežto cokoli nad 0,25 Google klasifikuje jako špatné a může to negativně ovlivnit pozici ve vyhledávání.

  • Dobré CLS skóre je ≤ 0,1, špatné > 0,25 podle aktualizované metodiky Core Web Vitals z roku 2024.
  • Hlavní příčiny: chybějící rozměry obrázků a iframes, pozdě načítané webové fonty (FOUT) a dynamicky vkládaný obsah.
  • CSS vlastnost aspect-ratio a deskriptor size-adjust u @font-face jsou dnes nejúčinnější techniky.
  • Animace pohybu používejte přes transform a opacity, nikdy přes top/left/width/height.
  • CLS měřte v produkci přes PerformanceObserver a CrUX dataset, nikoli pouze v Lighthouse.
  • Pro reklamy a embed widgety vždy rezervujte minimální výšku přes min-height nebo contain-intrinsic-size.

Co je CLS a jak se počítá

Honestly, CLS bývá nejvíc otravná metrika z Core Web Vitals, protože ji typicky odhalí až reálný uživatel. Cumulative Layout Shift je jedna ze tří hlavních metrik Core Web Vitals, která měří vizuální stabilitu stránky. Hodnota se počítá jako součin dvou složek pro každý neočekávaný posun rozložení: impact fraction (kolik procent viewportu posun ovlivnil) a distance fraction (jak daleko se prvky posunuly vůči viewportu). Výsledné skóre je součtem nejhoršího okna pěti sekund během celé životnosti stránky, tzv. session window, který Chrome zavedl v roce 2021 a od té doby je standardem.

Posun je považován za očekávaný (a tedy nepočítá se), pokud nastane do 500 ms po uživatelské interakci. Vše ostatní (pozdě dorazivší obrázky, fonty, banner cookie lišty, reklamy nebo skeleton screeny, které mizí) se započítává. Důležité je, že CLS sleduje pouze posuny existujících prvků. Nové prvky vložené do DOM bez posunutí stávajících skóre nezhoršují.

Podle oficiální dokumentace web.dev k CLS Google v roce 2024 zpřísnil výpočet pro mobilní zařízení a od té doby zhruba 38 % stránek po celém světě prošlo metriku jako "good". Není to úplně lichotivé číslo, takže příležitost ke zlepšení rozhodně existuje.

Jaké je dobré CLS skóre v roce 2026

Aktualizované prahové hodnoty pro rok 2026 vypadají takto.

KategorieMobilDesktopDopad na SEO
Dobré≤ 0,1≤ 0,1Pozitivní signál
Vyžaduje zlepšení0,1 až 0,250,1 až 0,25Neutrální
Špatné> 0,25> 0,25Negativní ranking faktor

Google používá 75. percentil dat z reálných uživatelů (CrUX dataset). To znamená, že pokud má 75 % vašich návštěvníků CLS pod 0,1, prošli jste. Není to průměr, je to percentil, takže odlehlé hodnoty (například první návštěva nového uživatele se studeným cache) můžou výrazně srazit hodnocení i u jinak dobře optimalizované stránky.

1. Vždy nastavujte rozměry obrázků a videí

Nejčastější příčina vysokého CLS? Obrázek bez deklarovaných rozměrů. Když prohlížeč začne renderovat HTML, neví, jak vysoký obrázek bude, dokud nestáhne hlavičku souboru. V té chvíli musí přerozdělit veškerý obsah pod ním. Řešení je triviální: vždy přidávejte atributy width a height.

<!-- Špatně: prohlížeč nezná rozměry -->
<img src="/hero.webp" alt="Hero obrázek">

<!-- Dobře: prohlížeč rezervuje místo dopředu -->
<img src="/hero.webp" alt="Hero obrázek"
     width="1200" height="630"
     loading="lazy" decoding="async">

Hodnoty width a height nemusí odpovídat skutečným pixelům na obrazovce. Moderní prohlížeče z nich pouze vypočítají poměr stran. Pokud používáte CSS max-width: 100%; height: auto;, obrázek se přizpůsobí kontejneru, ale rezervovaný prostor zůstane správný. Stejné pravidlo platí pro <video>, <iframe> a <canvas> elementy.

Pokud generujete obrázky dynamicky (CMS, headless framework) a neznáte rozměry dopředu, použijte build-time skript, který je dotáhne z metadat. V Next.js a Astro mají vestavěné komponenty <Image>, které tuto logiku řeší automaticky. V mém posledním projektu šlo CLS z 0,18 na 0,02 jen tím, že jsme do CMS šablony doplnili rozměry z EXIF dat při uploadu.

2. Použijte CSS aspect-ratio pro responzivní média

Pro responzivní kontejnery, kde se poměr stran mění podle viewportu, je elegantnější řešení CSS vlastnost aspect-ratio. Podporu má od roku 2021 ve všech moderních prohlížečích, takže ji můžete bez polyfillu nasadit kdekoli.

/* Rezervovaný prostor pro video embed */
.video-wrapper {
  aspect-ratio: 16 / 9;
  width: 100%;
  background: #f0f0f0; /* skeleton barva */
}

.video-wrapper iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

/* Hero obrázek se mění mezi mobilem a desktopem */
.hero-image {
  aspect-ratio: 4 / 3;
}
@media (min-width: 768px) {
  .hero-image { aspect-ratio: 21 / 9; }
}

Tato technika je obzvlášť cenná pro vložené YouTube/Vimeo přehrávače, mapy a sociální widgety. Místo abyste řešili padding hack s padding-top: 56.25%, deklarujete čistě sémanticky poměr stran a prohlížeč rezervuje místo ještě před načtením iframe obsahu.

3. Optimalizujte načítání webových fontů

Webové fonty způsobují CLS prostřednictvím jevu zvaného FOUT (Flash of Unstyled Text) nebo FOIT (Flash of Invisible Text). Když se konečně načte vlastní font a má jinou x-výšku nebo šířku znaků než fallback, text "skočí" a tabulky, nadpisy a tlačítka se posunou. V roce 2026 to řešíte kombinací font-display: swap a deskriptorů size-adjust, ascent-override a descent-override.

/* Vlastní font */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-var.woff2') format('woff2-variations');
  font-display: swap;
  font-weight: 100 900;
}

/* Upravený fallback, který napodobuje metriky Inter */
@font-face {
  font-family: 'Inter-fallback';
  src: local('Arial');
  size-adjust: 107%;
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
}

body {
  font-family: 'Inter', 'Inter-fallback', sans-serif;
}

Hodnoty pro size-adjust najdete pomocí nástroje Fallback Font Generator od ScreenSpan, který vypočítá přesné poměry pro každý fallback. Doplňkově použijte <link rel="preload" as="font" type="font/woff2" crossorigin> pro kritické fonty viditelné v hero sekci. Sníží to dobu, po kterou je viditelný fallback.

Pokud vás zajímá širší kontext optimalizace načítání kritických zdrojů, podívejte se i na náš návod jak zlepšit LCP skóre 7 ověřenými technikami, kde rozebíráme preload, priority hints a HTTP/3.

4. Rezervujte místo pro reklamy a embed widgety

Reklamní bannery jsou notoricky horší zdroj CLS. Načítají se asynchronně z externí domény, jejich rozměry nejsou v HTML deklarovány a často vyplňují prostor až poté, co prohlížeč vykreslil obsah pod nimi. Řešením je striktní rezervace prostoru, ideálně podle nejčastější velikosti banneru pro daný breakpoint.

<!-- Slot pro responsive ad -->
<div class="ad-slot" data-ad-id="header-banner">
  <ins class="adsbygoogle"
       style="display:block"
       data-ad-client="ca-pub-xxxxx"
       data-ad-slot="1234567890"
       data-ad-format="auto"></ins>
</div>

<style>
.ad-slot {
  min-height: 250px; /* nejmenší rozumná výška pro banner */
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fafafa;
}

@media (min-width: 768px) {
  .ad-slot { min-height: 90px; } /* leaderboard formát */
}
</style>

Stejný princip platí pro Twitter/X embedy, Instagram posty, mapy nebo komentářové widgety jako Disqus. Pokud nevíte přesnou výšku, použijte CSS min-height blízkou očekávané hodnotě. I příliš velká rezerva je lepší než žádná, protože když je rezervované místo větší než skutečný obsah, žádný posun nenastane.

5. Využijte content-visibility a contain-intrinsic-size

Pro dlouhé stránky se sekcemi pod fold (mimo viditelnou oblast) přišel Chrome v roce 2020 s vlastností content-visibility: auto, kterou v roce 2025 už podporuje Safari 18 i Firefox 125. Tato vlastnost umožňuje prohlížeči přeskočit renderování a layout pro elementy mimo viewport. Pozor ale, vyžaduje, abyste deklarovali jejich přibližnou velikost přes contain-intrinsic-size, jinak vzniká CLS.

article section {
  content-visibility: auto;
  contain-intrinsic-size: auto 800px;
}

Hodnota auto 800px říká: "pokud sekci ještě nevidíš, předpokládej, že je 800 px vysoká". Až prohlížeč sekci skutečně vyrenderuje, hodnotu si zapamatuje a použije přesnější odhad při dalším scrollu. Tato kombinace zrychluje první vykreslení o 20 až 40 % na dlouhých článcích a zároveň udržuje stabilní výšku stránky.

6. Animujte pouze transform a opacity

CLS započítává každý posun viditelných prvků, a špatně napsaná CSS animace je vůbec nejhorší pachatel. Animování vlastností jako top, left, width, height nebo margin způsobuje skutečný layout shift, který se započítává do skóre. Naopak transform a opacity běží na compositor threadu a CLS neovlivňují.

/* Špatně: spustí layout, započítá se do CLS */
.toast-bad {
  transition: top 300ms ease;
  top: -100px;
}
.toast-bad.visible { top: 20px; }

/* Dobře: GPU-akcelerované, nezasahuje do layoutu */
.toast-good {
  transform: translateY(-100px);
  transition: transform 300ms ease;
  opacity: 0;
}
.toast-good.visible {
  transform: translateY(20px);
  opacity: 1;
}

Pravidlo platí i pro JavaScript animace v knihovnách jako GSAP nebo Framer Motion. Vždy upřednostněte x, y, scale a opacity před přímou manipulací s box modelem. Pokud potřebujete změnit rozměr, použijte trik s transform: scale() a kompenzujte CSS proměnnými pro správný hit-area.

7. Nevkládejte obsah nad existující prvky

Klasický scénář CLS: stránka se načte, uživatel začne číst a po sekundě cookie banner (nebo notifikační lišta, nebo upsell promo) vyskočí nad hlavičku a celý obsah se posune dolů. Řešení je dvojí. Buď obsah zobrazte jako overlay přes position: fixed, nebo prostor pro něj rezervujte předem v HTML, ještě před jeho aktivací JavaScriptem.

<!-- Cookie banner jako fixed overlay -->
<div id="cookie-banner" hidden>...</div>
<style>
#cookie-banner {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 9999;
  padding: 16px;
  background: #fff;
  box-shadow: 0 -2px 8px rgba(0,0,0,.1);
}
</style>

Stejné pravidlo aplikujte na "fetch more" tlačítka, lazy-loaded sekce a komentáře. Pokud načítáte další obsah nekonečným scrollem, vkládejte ho pod aktuální pozici uživatele a nepřidávejte věci nad obrázky, které právě zaplňují místo. Naše příručka jak opravit špatné INP skóre rozebírá související problém s odezvou. Oba problémy spolu úzce souvisí, protože pomalý JS často způsobuje pozdní vkládání obsahu.

8. Měřte CLS v produkci, ne jen v Lighthouse

Lighthouse měří CLS pouze do okamžiku načtení stránky (lab data). Skutečné CLS zahrnuje celou dobu, kterou uživatel na stránce stráví, včetně scrollu, kliknutí na "load more" a otevírání modálů. Pro produkční měření použijte PerformanceObserver API s type: 'layout-shift' a posílejte výsledky do svého analytického nástroje.

let cls = 0;
let sessionValue = 0;
let sessionEntries = [];

new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Ignoruj posuny po uživatelské interakci
    if (entry.hadRecentInput) continue;

    const firstEntry = sessionEntries[0];
    const lastEntry = sessionEntries[sessionEntries.length - 1];

    // Sloučení do stejného session window (≤ 1 s mezi posuny, ≤ 5 s celkem)
    if (sessionValue &&
        entry.startTime - lastEntry.startTime < 1000 &&
        entry.startTime - firstEntry.startTime < 5000) {
      sessionValue += entry.value;
      sessionEntries.push(entry);
    } else {
      sessionValue = entry.value;
      sessionEntries = [entry];
    }

    // Aktualizuj CLS pouze pokud je tento session window horší
    if (sessionValue > cls) {
      cls = sessionValue;
      // Posílej do analytiky při unload nebo visibilitychange
      console.log('CLS:', cls.toFixed(4));
    }
  }
}).observe({ type: 'layout-shift', buffered: true });

// Pošli finální hodnotu při skrytí stránky
addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    navigator.sendBeacon('/analytics/cls',
      JSON.stringify({ cls, url: location.pathname }));
  }
});

Doplňkově sledujte CrUX data v Chrome User Experience Report. Jsou to anonymizovaná data od reálných uživatelů Chromu a Google je používá pro výpočet ranking signálu. Pro pohodlnější přehled doporučujeme PageSpeed Insights nebo CrUX BigQuery dataset, kde lze sledovat trendy v čase. Měření je klíčový krok stejně jako u dalších Core Web Vitals (viz naše průvodce optimalizací LCP pro propojený workflow).

Nástroje pro debugování CLS

Pokud chcete vizuálně vidět, které prvky způsobují posuny, máte k dispozici několik nástrojů. V Chrome DevTools otevřete panel Performance, nahrajte záznam a v sekci "Experience" uvidíte červené pruhy označující jednotlivé layout shifty s detailem, který element a o kolik se posunul. Ještě praktičtější je rozšíření Web Vitals Extension, které v reálném čase zobrazuje aktuální CLS, LCP a INP přímo v badge ikony.

Pro automatizované sledování v CI pipeline použijte Lighthouse CI nebo Sitespeed.io. Oba umí vyhodit chybu, pokud CLS překročí váš threshold v PR. Pro hlubší analýzu pak existuje Layout Instability API přímo v PerformanceObserver, který odhalí konkrétní DOM elementy s nejhoršími posuny. Můžete je pak označit data atributem a sledovat trendy. Při ladění jsem narazil na zajímavou věc: nejhorší posuny často vznikají z prvků, které vývojář vůbec nepodezírá (typicky placeholder, který "jen na chvíli" změní výšku).

Často kladené otázky

Jaké je dobré CLS skóre pro SEO?

Dobré CLS skóre je 0,1 nebo nižší na 75. percentilu reálných uživatelů. Hodnoty mezi 0,1 a 0,25 vyžadují zlepšení, vše nad 0,25 Google klasifikuje jako špatné a může negativně ovlivnit pozici ve vyhledávání. Limity jsou stejné pro mobilní i desktopové zařízení.

Co způsobuje vysoké CLS skóre?

Nejčastější příčiny jsou: obrázky a iframes bez nastavených rozměrů, webové fonty s odlišnými metrikami než fallback, dynamicky vkládané reklamy, cookie bannery nad obsahem a animace pohybu přes top/left místo transform. Méně časté, ale rovněž problematické jsou skeleton screeny, které mizí skokem.

Jak změřit CLS v produkci?

Použijte PerformanceObserver s typem layout-shift, agregujte hodnoty do session windows (≤ 1 s mezi posuny, ≤ 5 s celkem) a posílejte výsledky přes navigator.sendBeacon při visibilitychange. Doplňkově sledujte CrUX data, která Google používá pro ranking.

Ovlivňuje CLS pozici ve vyhledávání Google?

Ano. CLS je součástí Core Web Vitals, které Google používá jako ranking signál od června 2021. Stránky s dobrým CLS získávají preferenční zacházení v top-stories karuselu a v sekci Discover, zatímco stránky se špatným CLS mohou ztratit pozice u konkurenčních dotazů.

Proč mám v Lighthouse CLS 0, ale v terénu vysoké?

Lighthouse měří CLS pouze při načtení stránky v izolovaném prostředí bez interakce. Reálné CLS zahrnuje celou návštěvu: scroll, klikání, otevírání modálů, lazy načítaný obsah pod fold. Pro shodu nasimulujte v DevTools scroll throttling a vypněte cache, nebo se spoléhejte hlavně na data z CrUX.

Jak opravit CLS způsobený webovými fonty?

Použijte font-display: swap v kombinaci s upraveným fallback fontem přes size-adjust, ascent-override a descent-override deskriptory. Tím zajistíte, že fallback font má stejné metriky jako finální font a po načtení nedojde k posunu. Kritické fonty navíc předzaveďte přes <link rel="preload">.

Editorial Team
O Autorovi Editorial Team

Our team of expert writers and editors.