Mudança de layout cumulativa (CLS)

O que o Cumulative Layout Shift mede, como a pontuação é calculada (impacto × distância), session windows, limites, causas comuns e como corrigi-lo e depurá-lo.

Publicado pela primeira vez: 26 de jun. de 2026 · Última atualização: 3 de ago. de 2026 · Avançado
Idiomas

Cumulative Layout Shift (CLS) é o Core Web Vital de estabilidade visual — quanto conteúdo visível se move inesperadamente enquanto uma página está em uso. É uma pontuação sem unidade (impact fraction × distance fraction por mudança) e, desde junho de 2021, corresponde à maior session window de mudanças, não à soma de toda a vida da página. Bom é ≤ 0,1 no percentil 75 dos dados de campo; 0,1–0,25 precisa melhorar; > 0,25 é ruim. Os culpados comuns são imagens/anúncios/iframes/embeds sem dimensões, web fonts e conteúdo inserido acima da dobra — corrija-os reservando espaço (width/height ou aspect-ratio), ajustando font-display e animando com transform. O Lighthouse costuma ler perto de 0 porque não interage com a página nem executa todo o ciclo de vida — os dados de campo (CrUX) são o que o Google usa para ranking.

TL;DR — CLS é a Core Web Vital de estabilidade visual. Cada mudança recebe uma pontuação como impact fraction × distance fraction; a própria métrica é a maior janela de sessão de mudanças (≤ 1 s entre mudanças, janela de ≤ 5 s) — não a soma da vida útil, que era usada antes de junho de 2021. Bom é ≤ 0,1, precisa melhorar ≤ 0,25, ruim > 0,25, no percentil 75 dos dados de campo. Só mudanças visíveis na viewport contam; mudanças até 500 ms depois de uma entrada discreta são excluídas (rolagem não é). As causas são imagens/vídeos/anúncios/ iframes/embeds sem dimensões, fontes da web e conteúdo inserido acima do conteúdo existente; as correções são reservar espaço, font-display/size-adjust e animação apenas com transform. A armadilha a evitar: o Lighthouse (laboratório) costuma registrar quase 0 porque não interage com a página nem executa todo o ciclo de vida — dados de campo (CrUX) são o que o Google mede.

O que o CLS mede

O enquadramento do Google: “Cumulative Layout Shift (CLS) is a stable Core Web Vital metric. It’s an important, user-centric metric for measuring visual stability because it helps quantify how often users experience unexpected layout shifts.” (Tradução: “Cumulative Layout Shift (CLS) é uma métrica Core Web Vital estável. É uma métrica importante e centrada no usuário para medir a estabilidade visual porque ajuda a quantificar com que frequência as pessoas vivenciam mudanças de layout inesperadas.”) A palavra fundamental é inesperado — conteúdo que se move sozinho, não porque o usuário fez algo.

Ele faz parte do trio de Core Web Vitals com Largest Contentful Paint (carregamento) e Interaction to Next Paint (capacidade de resposta). Enquanto LCP e INP são medidos em milissegundos, CLS é a exceção: uma pontuação de proporção sem unidade. Isso confunde muita gente. Um CLS de 0,05 não é 50 ms. Ele não tem unidade de tempo alguma.

A fórmula: impacto × distância

Para cada mudança, o Google define assim:

layout shift score = impact fraction × distance fraction
  • Fração de impacto “measures how unstable elements impact the viewport area between two frames” — a área visível combinada que os elementos em movimento ocuparam (antes e depois), como proporção da viewport. (Tradução: “mede como elementos instáveis afetam a área da viewport entre dois quadros.”)
  • Fração de distância é “the greatest horizontal or vertical distance any unstable element has moved in the frame divided by the viewport’s largest dimension (width or height, whichever is greater).” (Tradução: “a maior distância horizontal ou vertical que qualquer elemento instável percorreu no quadro, dividida pela maior dimensão da viewport (largura ou altura, a que for maior).”)

As duas dimensões importam de forma independente. Um elemento pequeno que atravessa a maior parte da tela e um elemento grande que quase não se desloca podem receber pontuações muito diferentes. No exemplo trabalhado do web.dev, uma fração de impacto de 0.75 e uma fração de distância de 0.25 produzem uma pontuação de mudança de layout de 0.1875.

One shift scores the visible area affected multiplied by the farthest movement relative to the viewport. Fonte: web.dev

Three cards form the equation. Impact fraction is 0.75: the visible viewport area affected between two frames. Distance fraction is 0.25: the farthest movement divided by the viewport's largest dimension. Multiplying them produces a unitless individual layout-shift score of 0.1875. CLS ultimately keeps the largest session-window total, not a lifetime sum of every shift.

© Patrick Stox LLC · CC BY 4.0 ·

Janelas de sessão: a parte que todo mundo entende errado

Este é o fato mais distorcido sobre CLS — e aquele que eu mais quero que você guarde. CLS não é a soma de todas as mudanças ao longo da vida da página. Já foi assim — isso mudou em junho de 2021.

Hoje: “CLS measures the largest burst of layout shift scores for every unexpected layout shift that occurs during the entire lifecycle of a page.” (Tradução: “CLS mede o maior surto de pontuações de mudanças de layout para cada mudança inesperada que ocorre durante todo o ciclo de vida de uma página.”) Um surto é uma janela de sessão: “one or more individual layout shifts occur in rapid succession with less than 1-second in between each shift and a maximum of 5 seconds for the total window duration.” (Tradução: “uma ou mais mudanças de layout individuais ocorrem em rápida sucessão, com menos de 1 segundo entre cada mudança e duração total máxima da janela de 5 segundos.”) CLS é a pontuação da maior janela desse tipo — não a soma, nem a média.

Evidence for this claim CLS uses the largest session window of unexpected layout shifts, with gaps under one second and a maximum five-second window; recent discrete input can exclude a shift. Scope: Current CLS session-window and recent-input rules. Confidence: high · Verified: web.dev: Cumulative Layout Shift

Por que a mudança? A definição antiga, que somava tudo, punia discretamente páginas de longa duração. Um aplicativo de página única ou um feed de rolagem infinita acumulava mais CLS simplesmente por existir por mais tempo, mesmo que cada mudança individual fosse pequena e bem espaçada. A equipe Chrome Speed Metrics passou a usar uma janela de sessão máxima para não penalizar a duração e escolheu o máximo em vez da média para evitar um resultado perverso em que corrigir uma mudança pequena e secundária pudesse piorar sua pontuação. Quando a mudança foi lançada, nenhum domínio recebeu uma pontuação pior, a maioria não mudou e uma parcela de páginas com interface lenta e rolagem infinita melhorou. Se você ler um texto antigo que ainda diz “soma de todas as mudanças”, ele está desatualizado.

O que conta — e o que não conta

Três exclusões determinam o que realmente entra na sua pontuação:

  • O que está abaixo da dobra não conta. Só mudanças de conteúdo visíveis na viewport atual são pontuadas. Uma mudança no fim de uma página longa que o usuário nunca rola até alcançar não tem impacto. Na prática, isso significa que corrigir mudanças na viewport quase sempre traz um ROI maior do que perseguir mudanças muito abaixo na página.
  • Mudanças iniciadas pelo usuário ganham uma janela de 500 ms. “Layout shifts that occur within 500 milliseconds of user input will have the hadRecentInput flag set, so they can be excluded from calculations.” (Tradução: “mudanças de layout que ocorrem até 500 milissegundos depois da entrada do usuário terão a flag hadRecentInput definida e poderão ser excluídas dos cálculos.”) A posição do Google: mudanças “that occur in response to user interactions… are generally fine, as long as the shift occurs close enough to the interaction that the relationship is clear to the user.” (Tradução: “que ocorrem em resposta a interações do usuário… geralmente não são um problema, desde que a mudança ocorra perto o bastante da interação para que a relação fique clara para o usuário.”) Abrir um acordeão ou expandir um menu é um movimento esperado, então é perdoado.
  • Mas rolagem não é passe livre. A exclusão de 500 ms só se aplica a eventos discretos — toque, clique, tecla. Gestos contínuos (rolagem, pinça de zoom) não acionam a janela de exclusão. Se o conteúdo mudar enquanto alguém rola, isso ainda conta. Essa distinção está errada em muita cobertura; acerte-a.
Evidence for this claim A layout shift occurring within 500 milliseconds of a qualifying recent user input has hadRecentInput set and is excluded from CLS. Scope: field and lab Confidence: high · Verified: Cumulative Layout Shift (CLS)

Limiares e de onde vem a pontuação

“To provide a good user experience, sites should strive to have a CLS score of 0.1 or less,” (Tradução: “para oferecer uma boa experiência de usuário, os sites devem buscar uma pontuação CLS de 0,1 ou menos,”) medida no “the 75th percentile of page loads, segmented across mobile and desktop devices.” (Tradução: “o percentil 75 dos carregamentos de página, segmentado entre dispositivos móveis e desktop”.) As faixas completas são:

Evidence for this claim CLS is good at 0.1 or less and poor above 0.25, assessed at the 75th percentile of page loads. Scope: Current web.dev CLS field thresholds. Confidence: high · Verified: web.dev: Cumulative Layout Shift
  • Bom: ≤ 0,1
  • Precisa melhorar: 0,1 – 0,25
  • Ruim: > 0,25
Evidence for this claim CLS is good at 0.1 or less and poor above 0.25, assessed at the 75th percentile of page loads. Scope: Current web.dev CLS field thresholds. Confidence: high · Verified: web.dev: Cumulative Layout Shift

A linha de 0,1 não é arbitrária. A pesquisa de usuários do Google descobriu que “levels of shift from 0.15 and higher were consistently perceived as disruptive, while shifts of 0.1 and lower were noticeable but not excessively disruptive.” (Tradução: “níveis de mudança de 0,15 ou mais eram percebidos consistentemente como perturbadores, enquanto mudanças de 0,1 ou menos eram perceptíveis, mas não excessivamente perturbadoras.”) Eles chegaram a 0,1 em vez de um limite mais rígido em parte porque embeds de terceiros (anúncios, redes sociais) causam mudanças com tanta frequência que um padrão mais apertado seria impraticável na web real.

A parte do “percentil 75 dos dados de campo” é essencial, e nos leva à maior armadilha de medição.

Laboratório vs. campo: por que os números divergem

É aqui que a maioria das pessoas se dá mal. O Lighthouse e outras ferramentas de laboratório frequentemente registram um CLS próximo de 0,0 enquanto os dados de campo — e o Google — mostram algo muito pior. A diferença não significa que alguma das ferramentas esteja sendo desonesta; é uma questão de escopo. Uma execução de laboratório é um carregamento de página único, curto e roteirizado: ela não rola, não clica e não permanece ativa, então captura apenas as mudanças do carregamento inicial. Os dados de campo (CrUX) agregam visitas reais de muitos usuários, dispositivos e navegações ao longo de uma janela móvel, e CLS é definido durante o ciclo de vida inteiro da página — menus abrindo, conteúdo lazy carregando enquanto o usuário rola, anúncios tardios preenchendo o espaço, por quanto tempo a sessão durar. Uma execução curta de laboratório estruturalmente não consegue ver a maior parte disso.

Portanto, a regra prática é: use dados de laboratório para depurar uma mudança específica e dados de campo para conhecer sua pontuação real. O Google classifica usando dados de campo do Chrome User Experience Report (CrUX), exibidos no PageSpeed Insights e no Search Console. Se o Lighthouse registrar 0,0, mas o PageSpeed Insights mostrar 0,18, trate o número de campo como o que representa seus usuários reais — depois reproduza a mudança no laboratório interagindo com a página como um visitante real faria. Há mais duas diferenças de escopo importantes: a maioria das ferramentas, incluindo o Lighthouse, não propaga mudanças de layout de iframe para a pontuação do documento pai, embora o CrUX possa refleti-las, e o RUM baseado na API Layout Instability herda esse mesmo ponto cego de iframes — então seu monitoramento de usuários reais pode explicar menos um número do CrUX que parece pior do que mostra sua atribuição própria.

As causas comuns

Em ordem aproximada de frequência com que as vejo:

  1. Imagens e vídeos sem dimensões. Sem altura reservada, tudo abaixo salta quando a mídia carrega.
  2. Anúncios, embeds e iframes sem espaço reservado. Redes de anúncios fornecem tamanhos dinâmicos; embeds não informam sua altura antes de carregar.
  3. Conteúdo injetado dinamicamente acima do conteúdo existente. Banners de cookies, barras de notificação, widgets “relacionados”, promoções que carregam tarde — qualquer coisa que empurre para baixo o que já está na tela.
  4. Fontes da web (FOIT/FOUT). Quando a fonte personalizada substitui o fallback, o texto é refluído se suas métricas forem diferentes.
  5. Animações em propriedades que acionam layout. Animar top, left, margin, box-shadow ou box-sizing força o navegador a refazer o layout da página a cada quadro.

As correções

Cada correção reflete sua causa:

  • Imagens/vídeos — reserve o espaço. Defina os atributos width e height para que o navegador calcule a proporção e mantenha a caixa; combine com img { height: auto; width: 100%; } para comportamento responsivo, ou use a propriedade CSS aspect-ratio. Essa é a correção de CLS com maior alavancagem na maioria dos sites.
  • Anúncios/embeds/iframes — reserve espaço também. Use min-height ou aspect-ratio no contêiner; para espaços de anúncio, a orientação do Google Publisher Tag é direta: “Setting a fixed height and width directly on the ad slot div is the most effective way to do this.” (Tradução: “definir diretamente uma altura e uma largura fixas no div do espaço de anúncio é a forma mais eficaz de fazer isso.”) Para espaços de vários tamanhos, reserve o maior tamanho configurado. Empurre o conteúdo que carrega tarde para baixo, para que qualquer mudança residual fique abaixo da dobra.
  • Conteúdo dinâmico — não o insira no fluxo. Reserve um placeholder com o tamanho final ou sobreponha o conteúdo em vez de injetá-lo. Skeletons só ajudam se corresponderem exatamente às dimensões finais — um skeleton alguns pixels mais curto que o conteúdo real ainda causa uma mudança. Prefira carregamentos iniciados pelo usuário (“Carregar mais”) a inserções surpresa.
  • Fontes — corresponda às métricas. font-display: optional é o único valor com risco de CLS efetivamente zero; swap minimiza o texto invisível, mas pode causar deslocamento na troca. Melhor ainda, use as substituições de métricas CSS — size-adjust, ascent-override, descent-override, line-gap-override — para dimensionar a fonte fallback de modo que ela corresponda à fonte da web e a troca seja imperceptível. Faça preload das fontes críticas.
  • Animações — apenas transform. Anime com transform (translate, scale, rotate) em vez de top/left/margin. Animações baseadas em transform são compostas e não acionam layout, então não deslocam nada.

Como o CLS se encaixa nas classificações (mantenha a proporção)

CLS é uma entrada do sinal de experiência na página do Google. O Google diz que as Core Web Vitals são usadas por seus sistemas de classificação — mas a documentação atual da Pesquisa não publica um peso exato para CLS, uma regra de desempate ou uma garantia de classificação. Portanto, trate qualquer mecanismo específico (incluindo “é um desempate”) como uma aproximação operacional, não como um fato documentado. Meu conselho constante em tudo que escrevo sobre Core Web Vitals: entre na faixa “bom” e siga em frente. A maioria dos sites não verá um ganho significativo de classificação ou de negócio ao reduzir 0,08 para 0,02, e uma única pontuação raramente explica sozinha um resultado de receita ou conversão. CLS é requisito básico — você quer passar da barra, mas ele não deve virar o centro do seu programa de SEO em detrimento de LCP, INP ou, francamente, do seu conteúdo.

Duas observações operacionais que eliminam muita confusão:

  • O CrUX atrasa cerca de 28 dias. É uma janela móvel de 28 dias, então uma correção que você publica hoje não aparecerá completamente no PageSpeed Insights ou no Search Console por semanas. Não entre em pânico se o número não mudar na manhã seguinte.
  • O elemento atribuído frequentemente não é a causa raiz. A API Layout Shift Attribution informa qual elemento se moveu, mas, como observa o web.dev, “it’s possible that these elements are only indirectly related to the ‘root cause’ of layout instability.” (Tradução: “é possível que esses elementos estejam apenas indiretamente relacionados à ‘causa raiz’ da instabilidade de layout.”) O texto que saltou geralmente é vítima de uma imagem sem dimensões acima que carregou tarde — corrija a causa, não o sintoma. Trabalhe com um ciclo de tempo até o gatilho: anote o horário inicial da mudança e verifique o que mais mudou nessa mesma janela — uma requisição de rede terminando, uma imagem ou fonte chegando, um redimensionamento ou uma alteração de classe/estilo — e trate o nó atribuído como uma pista, não como prova, até associá-lo a esse gatilho.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.