Core Web Vitals9 min de leitura

Como Corrigir CLS (Cumulative Layout Shift)

Aprenda a identificar e eliminar mudanças de layout inesperadas que frustram usuários e prejudicam conversões.

O Que é CLS?

Cumulative Layout Shift (CLS) mede a estabilidade visual da sua página. Ele quantifica quanto o conteúdo se move inesperadamente durante o carregamento.

Exemplo clássico: Você está prestes a clicar em um botão, mas um anúncio carrega em cima e você clica no anúncio por engano. Isso é CLS ruim.

Valores de Referência:

  • Bom: Menos de 0.1
  • ⚠️ Precisa melhorar: 0.1 - 0.25
  • Ruim: Mais de 0.25

CLS é medido em pontos de impacto, não em segundos. Quanto mais conteúdo se move e quanto maior a distância, pior o score.

Por Que CLS é Importante?

📉 Impacto em Conversões

Estudos mostram que melhorar CLS de 0.25 para 0.05 pode aumentar conversões em 10-15%. Usuários desistem quando a página é instável.

😤 Frustração do Usuário

Cliques acidentais, perda do ponto de leitura e erros de digitação causam péssima experiência e aumentam bounce rate.

🔍 SEO

CLS é fator oficial de ranking do Google desde 2021. Sites com CLS ruim ranqueiam pior.

Causas Comuns de CLS

1️⃣Imagens Sem Dimensões

Problema: Navegador não sabe quanto espaço reservar até a imagem carregar, então o conteúdo abaixo "pula" quando a imagem aparece.

❌ Ruim:

<img src="/product.jpg" alt="Produto" />

✅ Bom:

<img
  src="/product.jpg"
  alt="Produto"
  width="600"
  height="400"
/>

// Ou com Next.js Image (calcula aspect ratio)
<Image
  src="/product.jpg"
  alt="Produto"
  width={600}
  height={400}
/>

2️⃣Anúncios e Embeds Sem Espaço Reservado

Problema: Anúncios, vídeos do YouTube, tweets embarcados carregam depois e empurram conteúdo para baixo.

Solução - Reserve espaço:

// CSS para manter aspect ratio
.ad-container {
  position: relative;
  width: 100%;
  padding-bottom: 56.25%; /* 16:9 aspect ratio */
  background: #f0f0f0; /* placeholder */
}

.ad-container iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

Dica: Use min-height para anúncios de tamanho variável.

3️⃣Fontes Web (FOIT/FOUT)

Problema: Fontes customizadas causam "flash" de texto invisível (FOIT) ou texto com outra fonte (FOUT), mudando o layout.

Solução:

@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: swap; /* ← Mostra fallback até carregar */
}

/* Ou use opcional */
@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: optional; /* ← Só mostra se já estiver em cache */
}

Melhor ainda: Use next/font que elimina CLS automaticamente.

4️⃣Conteúdo Dinâmico Injetado

Problema: Banners, alertas ou conteúdo carregado via JavaScript aparecem e empurram conteúdo existente.

❌ Ruim:

// Injeta banner no topo, empurra tudo
document.body.insertAdjacentHTML('afterbegin', '<div>Banner</div>');

✅ Bom:

// Renderiza placeholder no HTML inicial
<div id="banner-placeholder" style="height: 60px;"></div>

// Depois, popula o placeholder
document.getElementById('banner-placeholder').innerHTML = banner;

5️⃣Animações e Transições

Problema: Animar propriedades que causam reflow (width, height, top, left) provoca layout shifts.

❌ Ruim (causa CLS):

.box {
  transition: width 0.3s, height 0.3s;
}

✅ Bom (não causa CLS):

.box {
  transition: transform 0.3s, opacity 0.3s;
}

.box:hover {
  transform: scale(1.1); /* Não causa reflow */
}

Regra de ouro: Apenas anime transform e opacity para performance perfeita.

Checklist para Eliminar CLS

  • Todas as imagens têm width e height definidos (ou use Next.js Image)
  • Espaço reservado para anúncios e embeds antes de carregar
  • Fontes com font-display: swap ou opcional
  • Conteúdo dinâmico não injeta acima do conteúdo existente
  • Animações usam apenas transform e opacity
  • Evitar FOUC (Flash of Unstyled Content) carregando CSS crítico inline
  • Placeholders para carregamento de conteúdo (skeleton screens)

Como Detectar CLS

1. Chrome DevTools

  1. 1. Abra DevTools (F12)
  2. 2. Vá para a aba Performance
  3. 3. Marque "Web Vitals"
  4. 4. Clique Record e carregue a página
  5. 5. Veja os shifts marcados em vermelho no timeline

2. Layout Shift Regions

No DevTools:

  1. 1. Abra DevTools → More Tools → Rendering
  2. 2. Marque "Layout Shift Regions"
  3. 3. Recarregue a página
  4. 4. Áreas que se movem ficam destacadas em azul

3. CheckSpeed

Use o CheckSpeed para análise automática de CLS com identificação dos problemas e plano de ação.

Exemplo Prático: Skeleton Loading

Uma das melhores técnicas para evitar CLS é usar skeleton screens - placeholders que mantêm o layout estável durante o carregamento.

Exemplo React/Next.js:

// components/ProductCard.tsx
export function ProductCardSkeleton() {
  return (
    <div className="animate-pulse">
      <div className="bg-gray-200 h-48 w-full rounded"></div>
      <div className="mt-4 space-y-3">
        <div className="h-4 bg-gray-200 rounded w-3/4"></div>
        <div className="h-4 bg-gray-200 rounded w-1/2"></div>
      </div>
    </div>
  );
}

export function ProductCard({ product }) {
  return (
    <div>
      <img
        src={product.image}
        alt={product.name}
        width={300}
        height={200}
      />
      <h3>{product.name}</h3>
      <p>{product.price}</p>
    </div>
  );
}

// Uso
{isLoading ? <ProductCardSkeleton /> : <ProductCard product={product} />}

Casos Especiais

CLS em Single Page Apps (SPAs)

SPAs têm desafios únicos com CLS durante navegação:

  • Use Suspense (React) para manter layout durante transições
  • Mantenha header/footer fixos durante navegação
  • Pré-carregue rotas críticas

Next.js com Suspense:

import { Suspense } from 'react';
import { ProductListSkeleton } from './skeletons';

export default function ProductsPage() {
  return (
    <Suspense fallback={<ProductListSkeleton />}>
      <ProductList />
    </Suspense>
  );
}

Ferramentas e Recursos

Web Vitals Extension

Extensão do Chrome que mostra CLS em tempo real enquanto navega

Lighthouse CI

Teste CLS automaticamente em cada deploy

Search Console

Veja CLS de usuários reais do seu site (dados CrUX)

Conclusão

CLS é uma das métricas mais importantes para experiência do usuário. Sites com bom CLS mantêm usuários engajados, aumentam conversões e ranqueiam melhor.

As 3 regras de ouro para eliminar CLS:

  1. Sempre defina dimensões para imagens e embeds
  2. Reserve espaço antes de injetar conteúdo dinâmico
  3. Anime apenas transform e opacity

Seguindo essas regras, você eliminará 90% dos problemas de CLS!

Teste o CLS do Seu Site

Descubra quais elementos estão causando layout shifts no seu site e receba um plano de ação detalhado para corrigi-los.

Analisar Meu Site Gratuitamente