Zkratka proCumulative Layout Shiftkjumulejtiv lejaut šiftTakéCLS metrika, layout shift, posun obsahu při načítáníPokročilý

Definice

Cumulative Layout Shift je metrika ze sady Core Web Vitals, která měří, jak moc se viditelný obsah stránky během načítání a používání samovolně posune. Hodnota vzniká součtem jednotlivých posunů, kde každý se počítá jako podíl zasažené plochy viewportu vynásobený vzdáleností posunu. Za dobrou se považuje hodnota do 0,1.

Kategorie: Webové technologieAktualizováno

Než se na to spolehnete: Konkrétní parametry session window (1 s mezera, 5 s okno) a prahové hodnoty 0,1 / 0,25 odpovídají aktuální definici Google, ale metrika se v minulosti měnila; doporučuji ověřit proti aktuální dokumentaci web.dev. Odkaz na specifikaci Layout Instability API je na wicg.github.io, což nemusí projít filtrem povolených domén.

Proč se obsah vůbec posouvá

Prohlížeč vykresluje stránku postupně. Nejdřív dorazí HTML, pak obrázky, webfonty, reklamy a data z API. Pokud prvek nemá dopředu rezervované místo, prohlížeč ho nejdřív vykreslí s nulovou nebo špatnou výškou a po doručení skutečného obsahu rozvržení přepočítá. Všechno pod tímto prvkem skočí dolů. Uživatel, který zrovna mířil prstem na odkaz, klikne na něco jiného.

Cumulative Layout Shift tuhle zkušenost převádí na číslo. Metrika patří do sady Core Web Vitals a Google ji používá jako jeden ze signálů hodnocení stránky.

Jak se skóre počítá

Každý neočekávaný posun dostane vlastní skóre podle vzorce impact fraction × distance fraction. Impact fraction je podíl viewportu, kterého se posun dotkl (prvek zabíral 30 % obrazovky před posunem i po něm a posunul se o 20 % výšky, dohromady tedy zasáhl 50 % plochy). Distance fraction je vzdálenost posunu vůči delšímu rozměru viewportu. Výsledné číslo je bezrozměrné a nemá horní hranici.

Klíčové slovo je neočekávaný. Posun do 500 ms po uživatelské akci (kliknutí, stisk klávesy) se do skóre nepočítá, protože uživatel změnu sám vyvolal. Rolování a scroll takové výjimky nezakládají.

Session window

Původní definice sčítala všechny posuny za celou návštěvu, což trestalo dlouhé stránky s nekonečným rolováním. Dnešní podoba metriky bere nejhorší okno posunů: skupinu, kde mezi jednotlivými posuny není pauza delší než 1 sekunda a celé okno netrvá víc než 5 sekund. Reportuje se maximum přes všechna okna.

Odkud problémy prakticky pocházejí

  • Obrázky a videa bez rozměrů: chybějící width a height nebo aspect-ratio v CSS.
  • Webfonty: záměna záložního fontu za finální mění výšku textu (FOUT). Řeší se font-display: optional a laděním size-adjust u @font-face.
  • Vložený obsah: reklamní sloty, iframy, widgety a cookie lišty vkládané JavaScriptem nad existující obsah.
  • Dodatečně dotažená data: seznam produktů, který nahradí prázdný stav bez skeletonu odpovídající výšky.

Jak se CLS měří v praxi

Existují dvě roviny dat. Laboratorní nástroje (Lighthouse, PageSpeed Insights) simulují jedno načtení a zachytí jen posuny během něj. Terénní data z reálných uživatelů (CrUX, knihovna web-vitals) obsahují i posuny vyvolané chováním uživatele, a proto bývají horší. Pro hodnocení se používá 75. percentil návštěv: do 0,1 dobré, nad 0,25 špatné.

V prohlížeči je zdrojem dat PerformanceObserver s typem záznamu layout-shift, kde každý záznam nese hodnotu, příznak hadRecentInput a seznam zasažených uzlů. Právě ten seznam bývá při ladění cennější než samotné číslo, protože ukáže konkrétní element, který skáče.

Příklady z praxe

  1. Obrázek bez rezervovaného místa

    E-shop vykresluje kartu produktu s fotografií načtenou ze CDN. Bez atributů width a height prohlížeč nezná poměr stran a text popisku pod obrázkem po dotažení souboru skočí o několik set pixelů dolů. Doplnění rozměrů (nebo aspect-ratio) prohlížeči umožní místo rezervovat ještě před stažením souboru.

    <!-- skáče -->
    <img src="/produkt.jpg" alt="Židle">
    
    <!-- místo je rezervované předem -->
    <img src="/produkt.jpg" alt="Židle" width="800" height="600">
    
    <style>
      img { max-width: 100%; height: auto; }
    </style>
  2. Měření posunů v reálném provozu

    Vývojář chce vědět, které elementy posun způsobují u skutečných návštěvníků, ne jen v Lighthouse. PerformanceObserver sleduje záznamy typu layout-shift, odfiltruje ty vyvolané uživatelskou akcí a odešle spolu s hodnotou i selektor zasaženého uzlu do analytiky.

    let cls = 0;
    new PerformanceObserver((list) => {
      for (const entry of list.getEntries()) {
        if (entry.hadRecentInput) continue; // posun po interakci se nepočítá
        cls += entry.value;
        for (const source of entry.sources ?? []) {
          console.log('posouvá se:', source.node, entry.value);
        }
      }
    }).observe({ type: 'layout-shift', buffered: true });

Časté omyly

MýtusCLS se měří jen během načítání stránky, takže stačí optimalizovat first paint.
Ve skutečnostiCLS se sbírá po celou dobu života stránky, včetně posunů, které vyvolá lazy loading při rolování nebo pozdě vložená cookie lišta. Terénní data proto bývají výrazně horší než laboratorní měření z Lighthouse.
MýtusJakýkoli pohyb obsahu zhoršuje CLS, takže animace jsou zakázané.
Ve skutečnostiDo skóre se počítají jen posuny rozvržení. Animace přes transform a opacity rozvržení nemění a CLS neovlivní. Stejně tak se nepočítá změna do 500 ms po uživatelské akci, například rozbalení akordeonu po kliknutí.
MýtusNulové CLS znamená, že stránka je rychlá.
Ve skutečnostiCLS měří vizuální stabilitu, nikoli rychlost. Stránka se může načítat pomalu a mít přitom CLS 0. Rychlost pokrývají jiné metriky, zejména LCP a INP.

Časté dotazy

Jaká hodnota CLS se považuje za dobrou?
Za dobrou hodnotu CLS se považuje 0,1 a méně, pásmo od 0,1 do 0,25 znamená potřebu zlepšení a nad 0,25 je výsledek hodnocen jako špatný. Hranice se posuzují na 75. percentilu reálných návštěv, měřeno zvlášť pro mobilní a desktopová zařízení. Znamená to, že čtvrtina nejhorších návštěv se do limitu vejít nemusí, ale zbytek ano. Laboratorní hodnota z Lighthouse je jen orientační, protože nezachytí posuny vzniklé při rolování a interakci.
Jak zabránit posunu způsobenému webfonty?
Posunu z webfontů se předchází třemi kroky. Prvním je preload souboru s fontem, aby dorazil dřív než první vykreslení textu. Druhým je volba font-display: optional, při které prohlížeč použije webfont jen tehdy, stihne-li se načíst včas, a jinak zůstane u záložního fontu bez pozdější výměny. Třetím je sladění metrik záložního a cílového fontu pomocí vlastností size-adjust, ascent-override a descent-override v pravidle @font-face, aby se výška řádků po výměně nezměnila.
Počítá se do CLS posun, který vyvolá uživatel kliknutím?
Posun vyvolaný uživatelskou akcí se do CLS nezapočítá, pokud nastane do 500 milisekund po kliknutí, stisku klávesy nebo podobné interakci. Prohlížeč takový záznam označí příznakem hadRecentInput. Rozbalení menu, otevření akordeonu nebo načtení dalších položek po stisku tlačítka tedy skóre nezhoršují. Výjimka se ale nevztahuje na rolování ani na změny, které přijdou později než půl sekundy po akci: pomalá odezva serveru může způsobit, že se posun do metriky nakonec započítá.
Jak najít konkrétní prvek, který posun způsobuje?
Konkrétní viník se hledá v záznamech typu layout-shift, které vrací PerformanceObserver. Každý záznam obsahuje pole sources s odkazem na DOM uzly a s obdélníky před posunem a po něm. V Chrome DevTools stejnou informaci nabízí panel Performance, kde jsou posuny vyznačené na časové ose, a experimentální vrstva Layout Shift Regions zvýrazní posouvající se oblasti přímo ve stránce. Pro produkci se hodí knihovna web-vitals, která odesílá atribuci do analytiky.

Zdroje

  1. Core Web Vitals(otevře se v novém okně)Google Search Central
  2. LayoutShift(otevře se v novém okně)MDN Web Docs
  3. CSS aspect-ratio(otevře se v novém okně)MDN Web Docs

Související pojmy

Potřebujete to vyřešit v praxi?

Poradíme, jak na to ve vašem projektu

Vysvětlit pojem je jedna věc, navrhnout kolem něj funkční řešení druhá. Ozvěte se a probereme, co dává smysl u vás.