Um botão que muda de lugar quando a imagem chega não parece um detalhe de performance. Para quem estava prestes a tocar, é um erro de interface.
Landing pages criadas por IA costumam combinar hero responsiva, fontes web, animações, embeds, banners e formulários. Se o HTML não reserva espaço para cada parte, o navegador monta uma primeira versão e reorganiza a página conforme os recursos aparecem.
Cumulative Layout Shift, ou CLS, mede esses deslocamentos inesperados. Corrigir a métrica exige descobrir qual elemento se moveu, qual conteúdo causou o movimento e em que momento da visita ele ocorreu.
O que conta como layout shift
Um layout shift acontece quando um elemento visível muda sua posição inicial entre dois frames. A pontuação considera quanto da viewport foi afetado e a distância do movimento.
Nem toda mudança entra na pontuação. A API marca hadRecentInput quando o deslocamento acontece até 500 ms depois de uma entrada qualificada, como clique, toque ou tecla; esses shifts ficam fora do CLS. O navegador aplica essa janela de tempo, não uma análise de causalidade. Scroll e hover não recebem a mesma exclusão, uma expansão que começa depois dos 500 ms volta a contar e até um movimento não relacionado pode ser excluído se cair dentro da janela. O guia atual do web.dev sobre CLS detalha esse critério.
O ponto difícil está nos movimentos que surpreendem:
- imagem ocupa espaço só depois do download;
- banner aparece acima do título;
- fonte muda a quebra de linha;
- embed cresce quando inicializa;
- mensagem de erro empurra o botão;
- anúncio ou recomendação entra tarde;
- componente hidratado troca o markup inicial;
- animação altera largura, altura ou posição.
Meça além do carregamento inicial
Ferramentas de laboratório capturam bem os shifts que acontecem durante a abertura. Elas podem perder mudanças tardias após scroll, consentimento, validação ou navegação em uma página mantida aberta.
Combine:
- PageSpeed Insights para dados de campo e laboratório;
- relatório de Core Web Vitals no Search Console quando houver tráfego;
- painel Performance do Chrome DevTools para reproduzir localmente;
- biblioteca
web-vitalsquando o produto precisa relacionar a métrica a uma versão ou rota.
A faixa boa de CLS é até 0,1 no 75º percentil de visitas, separada entre mobile e desktop. O guia de Core Web Vitals para sites criados por IA mostra como registrar uma linha de base sem confundir laboratório e campo.
Antes de editar, anote:
URL:versão publicada:dispositivo e largura:CLS de campo:CLS de laboratório:elemento que se moveu:conteúdo que causou o movimento:momento da visita:Reserve espaço para imagens
O navegador consegue calcular a proporção de uma imagem antes do download quando o HTML informa largura e altura.
<img src="/assets/case-study.webp" width="1200" height="800" alt="Painel com o resultado do projeto" loading="lazy"/>O CSS pode manter a imagem fluida:
img { max-width: 100%; height: auto;}Os atributos não obrigam a renderização em 1200 por 800 pixels. Eles fornecem a proporção intrínseca de 3 por 2. A documentação da MDN sobre aspect ratio explica como a reserva evita o salto causado por mídia que chega depois da primeira pintura.
Para um contêiner cuja mídia varia:
.video-frame { aspect-ratio: 16 / 9; overflow: hidden; background: #111827;}
.video-frame > iframe { width: 100%; height: 100%; border: 0;}Use a proporção do conteúdo real. Uma caixa 16 por 9 que recebe um vídeo vertical evita o shift, mas cria corte ou espaço vazio.
O artigo sobre otimização de imagens cobre formato, srcset, sizes e lazy loading. Estabilidade depende também de reservar a geometria correta.
Trate imagens responsivas como uma família
Todas as opções de um srcset devem representar o mesmo enquadramento ou declarar a proporção adequada para cada condição.
<picture> <source media="(max-width: 640px)" srcset="/assets/hero-mobile.avif" width="720" height="900" /> <img src="/assets/hero-desktop.avif" width="1440" height="810" alt="Produto em uso durante uma reunião" fetchpriority="high" /></picture>Confirme o comportamento nos navegadores suportados e teste a largura em que a fonte muda. Se a arte mobile e desktop têm proporções diferentes, a área reservada também precisa acompanhar a seleção.
Não aplique loading="lazy" à imagem de LCP. Isso atrasa a descoberta, embora não seja por si só uma correção de CLS. O guia de priorização de recursos separa tempo de descoberta, prioridade e tamanho.
Dê dimensões a vídeos e embeds
Iframes de vídeo, mapas, calendários e formulários externos costumam iniciar com altura pequena e crescer depois que o script remoto carrega.
Escolha uma destas estratégias:
- reserve uma proporção fixa;
- use uma altura mínima compatível com o estado final;
- mostre um placeholder com as mesmas dimensões;
- carregue o embed após ação do visitante sem mover conteúdo vizinho;
- abra a experiência externa em uma nova rota quando ela não cabe na landing.
Um placeholder só funciona quando ocupa o espaço final. Um esqueleto de 200 px substituído por um calendário de 700 px ainda empurra a página.
Evite inserir banners acima do conteúdo
Banners de cookies, campanhas e avisos podem deslocar toda a primeira dobra quando entram no fluxo depois da pintura.
Opções mais previsíveis:
- reservar a altura desde o HTML inicial;
- fixar o aviso sem cobrir controles essenciais;
- renderizar o estado de consentimento no primeiro markup;
- inserir conteúdo novo abaixo do ponto de leitura atual.
Se usar posição fixa, teste zoom, teclado virtual, safe areas e leitores de tela. Tirar o banner do fluxo não permite esconder conteúdo ou bloquear o botão de recusa.
Controle a troca de fontes
Uma fonte de fallback e a fonte final podem ter métricas diferentes. O título quebra em outra linha, aumenta a seção hero e move tudo abaixo.
Revise:
- pesos realmente usados;
- subconjuntos de caracteres;
- origem e tempo de download;
font-displayescolhido;- fallback com proporções semelhantes;
size-adjust,ascent-override,descent-overrideeline-gap-overridequando houver medição para configurá-los.
Não copie valores de outro projeto. Métricas erradas podem cortar texto ou criar outra mudança. O guia de fontes web em sites criados por IA mostra como inventariar famílias e pesos antes de alterar o carregamento.
Reserve os estados do formulário
Mensagens de validação e sucesso aparecem após interação. Mesmo quando o shift fica fora do cálculo de CLS por estar ligado ao clique, o movimento pode atrapalhar a próxima ação.
.field-message { min-height: 1.5em;}Use a área reservada para uma mensagem curta. Erros longos devem quebrar linha sem sobrepor outros campos. Para um alerta global, posicione-o onde a expansão não mova o botão que a pessoa está usando.
O artigo sobre teste de formulários ajuda a percorrer estados vazios, inválidos, carregando, sucesso e falha.
Anime sem recalcular o layout
Transições de top, left, width e height alteram geometria. Quando a intenção é mover ou redimensionar visualmente sem reorganizar os vizinhos, prefira transform.
.card { transition: transform 180ms ease, opacity 180ms ease;}
.card[inert] { transform: translateY(8px); opacity: 0; pointer-events: none;}Use o atributo booleano inert enquanto o card estiver oculto e remova-o na mesma transição que revela o conteúdo. Ele retira o card e seus descendentes da navegação por foco, dos eventos de interação e da árvore de acessibilidade. aria-hidden="true" sozinho não impede que um link ou botão transparente receba foco ou clique. Se o foco já estiver dentro do card, mova-o para um controle visível antes de ativar inert.
Nem todo movimento deve ser convertido mecanicamente. Um acordeão precisa abrir espaço para o conteúdo e continua sendo uma alteração de layout esperada. Preserve foco, leitura e prefers-reduced-motion.
Cuidado com conteúdo fora da viewport
content-visibility: auto pode evitar parte do trabalho de renderização de seções distantes. Para manter a rolagem estável, combine a propriedade com uma estimativa de tamanho:
.below-fold-section { content-visibility: auto; contain-intrinsic-size: auto 720px;}A estimativa ruim pode produzir mudança na barra de rolagem quando o conteúdo real for renderizado. Use a propriedade depois de medir se layout e pintura fora da tela são um custo relevante. Não aplique em conteúdo da primeira dobra.
Encontre a causa do movimento
O elemento destacado pelo DevTools é o que se moveu. A causa pode estar acima dele.
Se o botão desceu, procure:
- imagem anterior sem dimensões;
- fonte que alterou o título;
- banner inserido no topo;
- componente que trocou altura;
- CSS carregado tarde;
- markup de servidor diferente do estado hidratado.
Corrigir o botão com position: absolute pode apenas esconder o sintoma e criar sobreposição. Preserve o fluxo quando ele representa a estrutura da página.
Valide em estados reais
Repita a visita em:
- mobile e desktop;
- cache vazio e quente;
- conexão lenta;
- fonte carregada e bloqueada;
- consentimento novo e já salvo;
- formulário com erro e sucesso;
- embed disponível e indisponível;
- scroll até o fim;
- navegação de volta pelo histórico;
- URL padrão e domínio próprio.
Uma gravação de laboratório sem interação não cobre essa lista. Se os dados de campo apontam CLS e o laboratório não reproduz, adicione medição por versão antes de tentar correções amplas.
Republique sem trocar o endereço
Depois da correção:
- rode build e checks do projeto;
- abra o resultado local sem iniciar um servidor quando o artefato permitir inspeção direta;
- confirme dimensões, rotas e assets do pacote;
- aplique a mudança pelas file tools e publique pelo fluxo de Publicação;
- preserve o Site ID e o slug;
- abra a URL final e percorra os estados que causavam o movimento;
- compare laboratório e dados de campo quando a nova versão acumular visitas.
Se o HTML novo referencia imagens com hash, confirme que os novos assets existem em public/ e remova explicitamente os que ficaram obsoletos. O guia para evitar assets antigos após republicar mostra como impedir a mistura entre HTML e mídia de versões diferentes.
Prompt para uma revisão focada
Revise os layout shifts desta landing page sem publicar ainda.
URL e versão: [URL e commit]Dispositivo e largura: [contexto]Evidência: [CLS de campo, laboratório ou trace]Estado que dispara o movimento: [passos]
1. Identifique o elemento que se move e o conteúdo que causou o movimento.2. Separe mídia, fonte, conteúdo assíncrono, hidratação e animação.3. Reserve espaço com dimensões compatíveis com o estado final.4. Preserve design, responsividade, acessibilidade e conversão.5. Faça uma mudança pequena e rode os checks do projeto.6. Mostre como repetir a medição antes de republicar.Uma landing estável não precisa parecer imóvel. Ela precisa respeitar o espaço que prometeu. Imagens, fontes e integrações podem chegar depois sem arrancar o controle debaixo do dedo de quem já começou a usar a página.
