Corrigir o Layout shift culprits no Lighthouse e PageSpeed

O que se moveu enquanto a página carregava, como verificar o elemento que o Lighthouse culpa e como corrigir mudanças causadas por imagens, web fonts, anúncios, barras e CSS tardio.

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-11-05

Porque é que o Layout shift culprits está vermelho no PageSpeed Insights?

O Layout shift culprits fica vermelho quando as mudanças de layout durante o carregamento somam um CLS de 0,1 ou mais: "As mudanças de layout ocorrem quando os elementos se movem sem qualquer interação do utilizador." O Lighthouse chamava-lhe Avoid large layout shifts. Lista o que se moveu e tenta adivinhar a causa. Reserve espaço para o que chega tarde: largura e altura nas imagens, altura nos espaços de anúncios.

Quer apenas a solução rápida? Salte para imagens, web fonts, anúncios e embeds ou banners.

Como ler a tabela do Layout shift culprits?

O Lighthouse regista um carregamento da página num ecrã do tamanho de um telemóvel e lista as mudanças de layout em rajadas (mudanças que ocorrem com menos de um segundo de intervalo entre si), uma tabela por rajada. O aviso fica vermelho quando a pior rajada pontua 0,1 ou mais, e cinzento abaixo disso. Procure obter 0 mesmo quando estiver cinzento: uma mudança inferior a 0,1 continua a mover o texto que o visitante está a ler.

Numa página de receita que criei ao estilo de um blogue de culinária em WordPress, com o título numa web font, um plugin de newsletter, um anúncio sob o cabeçalho e um plugin de cartão de receita, o aviso ficou vermelho com uma rajada de 0,241.

O diagnóstico Layout shift culprits do Lighthouse a vermelho numa página de receita: Total de 0,241 e quatro mudanças. Os elementos que se moveram são div.entry-content, main, o título do cartão de receita e article. Sob três deles, a linha de causa é Unsized image element a apontar para a imagem de destaque, que tem width 1200 e height 675; a linha do tipo de letra também diz Web font, e a linha do cartão de receita indica a foto da receita.

O aviso da página de receita no Lighthouse 13.5, telemóvel, throttling simulado como no PageSpeed Insights.

  • Total é a pontuação da rajada; o Total da pior rajada é o CLS reportado pelo Lighthouse.
  • Element é o que mais se moveu nessa mudança, muitas vezes um contentor grande como <main>. O que o empurrou situa-se normalmente acima.
  • Layout shift score é a parcela dessa mudança no Total.
  • A linha sob cada entrada é a estimativa da causa feita pelo Lighthouse: "Unsized image element" com a imagem, ou "Web font" com o ficheiro do tipo de letra. Uma entrada pode ter ambos ou nenhum.

Na página de receita, o Lighthouse indicou a imagem errada em três das quatro mudanças: verifique que elemento se moveu realmente antes de alterar qualquer coisa.

Porque é que a página salta durante o carregamento?

O visitante começa a ler e o texto desliza, ou toca num link e acerta no que se moveu para o seu lugar.

O browser renderiza a página com o que tem. O que chega mais tarde sem espaço à espera empurra o conteúdo abaixo: uma imagem sem dimensões começa com altura zero, uma web font torna o título mais largo do que o fallback tornava. Cada movimento é uma mudança de layout, pontuada pela fração de ecrã que se moveu e pela distância. Mudanças com menos de um segundo de intervalo formam uma rajada, e o CLS é a pontuação da pior rajada; assim, pequenas mudanças consecutivas acumulam-se.

Na página de receita, cada causa fica abaixo de 0,1 isoladamente, e as quatro ocorrem numa única rajada:

Causa na página de receitaCLS isoladoApós a correção
Web font do título0,0350
Foto da receita sem width e height0,0360
Barra de newsletter acima do cabeçalho0,0580
Anúncio num espaço vazio0,0540
Todas as quatro juntas0,2410

Todas as quatro juntas pontuam mais do que a soma das linhas, porque na página completa o tipo de letra e a foto movem, cada um, uma área maior do ecrã. A correção das quatro fez a pontuação de Performance em telemóvel subir de 87 para 100, com FCP, LCP e Total Blocking Time inalterados. O CLS vale um quarto dessa pontuação, mas a Google posiciona a página com base no CLS que os visitantes reais obtêm.

A página de receita num telemóvel no seu first paint: cabeçalho, um rótulo de anúncio vazio, o título em duas linhas no tipo de letra de fallback, a linha de autor e a foto de destaque.

Antes, first paint

A mesma página dois segundos mais tarde: uma barra de newsletter verde acima do cabeçalho, um anúncio abaixo, o título em três linhas na web font e a foto mais abaixo do que a caixa tracejada que marca onde estava no first paint.

Antes, aos 2 segundos

A página corrigida no seu first paint: uma faixa vazia onde a barra irá ficar, um espaço de anúncio vazio na sua altura total e o título já em três linhas no tipo de letra de fallback ajustado.

Depois, first paint

A página corrigida dois segundos mais tarde: a barra e o anúncio preencheram o seu espaço, o título está na web font e a foto está onde estava no first paint.

Depois, aos 2 segundos

A página de receita no tamanho de telemóvel do Lighthouse. A caixa tracejada marca onde a foto estava no first paint.

O Lighthouse culpou o elemento certo?

O Lighthouse deduz a causa pelo timing: uma web font que terminou o download imediatamente antes da mudança, uma imagem que o browser desenhou logo a seguir. Assim, uma imagem que foi apenas empurrada pode surgir listada como "Unsized image element". A imagem de destaque da página de receita tem width="1200" height="675", mas o Lighthouse indica-a sob as mudanças da fonte, da barra de newsletter e do anúncio. Para uma linha sem indicação de causa por baixo, comece no passo 2.

  1. A imagem indicada tem dimensões? "Image elements do not have explicit width and height", sob Diagnostics no mesmo relatório, lista as imagens sem dimensões. Nas DevTools, o separador Computed da imagem mostra uma proporção em aspect-ratio (auto 1200 / 675) quando o espaço está reservado, e apenas auto quando não está. Uma imagem com dimensões não causou a mudança, a menos que o tema defina width: auto (Unsized image element abaixo): verifique a outra linha sob a entrada, muitas vezes "Web font", ou avance para o passo 2.
  2. O que surgiu nesse momento? Grave um recarregamento no painel Performance. Cada mudança é um losango roxo na faixa Layout shifts; passe o cursor por cima para ver a pontuação e uma captura de ecrã desse momento com a área deslocada assinalada. Na página de receita, a mudança de 0,0583 mostra a barra verde da newsletter que tinha acabado de surgir no topo. Para mudanças durante o scroll, clique em Record, faça scroll e clique em Stop.
  3. Bloqueie o elemento suspeito e recarregue. No painel Network, clique com o botão direito no pedido suspeito, como o ficheiro do tipo de letra ou a tag de anúncio, escolha Block requests, depois Block request URL e grave novamente. Um losango que desapareça pertencia a esse pedido: bloquear o tipo de letra da página de receita removeu uma mudança e manteve as outras três. Desmarque o bloqueio na gaveta Request conditions no final.
Painel Performance do Chrome DevTools: a faixa Layout shifts com quatro losangos no pior cluster de layout shifts, a tooltip da mudança de 0,0583 a mostrar a página com uma barra de newsletter verde que acabou de surgir acima do cabeçalho e o diagnóstico Layout shift culprits à esquerda a listar duas imagens sem dimensões e uma web font.

Passo 2 na página de receita: Chrome 155, Slow 4G e abrandamento de CPU de 4×.

Sem as DevTools, o cRUM no CoreDash faz esta verificação: coloca um trace do Chrome da página ao lado do que os visitantes reais obtiveram, indica o elemento que se moveu e mostra o que o visitante fez imediatamente antes. A captura de ecrã abaixo é de uma página diferente: comece em Chrome trace e Real users.

CoreDash cRUM para uma página em mobile: Chrome trace no topo e, sob Real users, os painéis When it shifts, What shifts e What preceded it.

CoreDash cRUM para uma página em acme-pagespeed.com, mobile.

Que elementos se movem para os visitantes reais?

O Lighthouse carrega a página uma única vez, como um visitante que entra pela primeira vez, e nunca faz scroll nem toca no ecrã. Os seus field data contêm todas as visitas reais, incluindo o anúncio a meio de um artigo que carrega quando o visitante faz scroll até ele e o cabeçalho que encolhe com o scroll. Quando o Lighthouse está limpo ou cinzento e o Search Console indica que o CLS é fraco, as mudanças acontecem normalmente após o carregamento.

No CoreDash, defina o dispositivo para mobile e agrupe o CLS por Attribution Element (CLS) para ver que elementos se moveram; Last interaction (CLS), sob More dimensions, indica se isso aconteceu após um scroll. Para encontrar o que empurrou esses elementos, grave essa página no painel Performance enquanto faz scroll (passo 2 da verificação acima).

CoreDash, Cumulative Layout Shift por Attribution Element (CLS) em mobile: por elemento, o CLS p75, uma classificação de desempenho, a distribuição e as sessões; as linhas incluem main#main.site-main, o nome da receita, um espaço de anúncio no conteúdo, a navegação e o rodapé.

CoreDash em mobile, p75: comece pelo CLS mais elevado.

Como resolver o Layout shift culprits?

Comece pela maior mudança na tabela com o Total mais elevado, assim que a verificação acima tiver confirmado a respetiva causa.

Unsized image element

Uma imagem sem dimensões começa com altura zero e empurra tudo o que estiver abaixo quando carrega. O WordPress adiciona width e height às imagens da biblioteca multimédia; as imagens geradas pelo próprio tema, page builder, slider ou plugin muitas vezes não os têm, como a foto do cartão de receita. Se não puder alterar o tema, o WP Rocket adiciona as dimensões em falta (Media, Add missing image dimensions); num template, escreva-as diretamente:

<img src="shakshuka.jpg" width="800" height="600" alt="Shakshuka in the pan">
img { max-width: 100%; height: auto; }

O browser converte os dois atributos numa proporção e reserva a altura correta em qualquer largura de ecrã antes de o ficheiro chegar. Um width: auto no CSS do tema anula essa proporção (auto sizing de imagens). No Shopify, o filtro image_tag adiciona as dimensões; um tema ou app que escreva a sua própria tag <img> precisa de width="{{ image.width }}" height="{{ image.height }}". No Next.js, o next/image precisa de width e height, ou de fill dentro de um elemento pai com dimensões próprias.

Web font

O título surge primeiro no tipo de letra de fallback e depois na web font, que é mais larga ou mais estreita: as linhas quebram em palavras diferentes e tudo o que está abaixo move-se. No WordPress (Additional CSS) e no Shopify (na folha de estilos do tema sob Edit code; uma atualização do tema pode anular isso), adicione uma font face de fallback que redimensiona um tipo de letra local para as medidas da web font. No Next.js, o next/font adiciona um fallback correspondente. A fonte do título da página de receita:

@font-face {
  font-family: "Young Serif Fallback";
  src: local("Times New Roman"), local("Liberation Serif");
  size-adjust: 131%;
  ascent-override: 79.85%;
  descent-override: 27.94%;
  line-gap-override: 0%;
}
h1 { font-family: "Young Serif", "Young Serif Fallback", serif; }

Um size-adjust de 122% obtido numa calculadora ainda deixava ali um CLS de 0,029; 131% resultou em 0. O artigo Font display inclui a regra para Android, como obter os seus próprios valores e o font-display: optional, que elimina a mudança e apresenta o fallback a quem visita pela primeira vez.

Anúncios, vídeos e outros embeds

O script de anúncios coloca o respetivo iframe no espaço após o leilão; se o espaço estava vazio, tudo o que está abaixo desce a altura do anúncio. De acordo com o State of Web Vitals, 89% dos sites sem redes de anúncios passam no CLS em telemóveis, contra 73% dos sites com duas ou mais redes. Isto é uma correlação.

No tema ou no plugin de anúncios, atribua ao contentor do anúncio a altura do formato mais frequente e defina o iframe como bloco:

.ad-slot { min-height: 50px; }
.ad-slot iframe { display: block; }

Por defeito, um iframe alinha-se pela linha de texto, pelo que o espaço reservado na página de receita ainda crescia 8 píxeis até o iframe passar a bloco. Mantenha o espaço aberto quando não houver anúncio: fechá-lo move a página tanto quanto preenchê-lo. Os Auto ads do AdSense surgem onde a Google decide: exclua as áreas no primeiro ecrã (Ad settings, Excluded areas) e coloque aí uma unidade de anúncio manual num espaço com dimensões definidas.

O YouTube, mapas e outros embeds também são iframes, e num iframe os atributos width e height não definem uma proporção: com height: auto, ele encolhe para cerca de 150 píxeis. Defina um aspect-ratio no iframe ou use uma facade — uma miniatura com dimensões que se converte no iframe com um clique (YouTube, Google Maps):

.video-embed iframe { width: 100%; height: auto; aspect-ratio: 16 / 9; }

Barras e banners inseridos por scripts

Uma barra de newsletter ou uma faixa de portes grátis que um script coloca acima do cabeçalho empurra a página inteira para baixo.

Comece pela opção de layout do plugin ou da app: uma barra inferior, uma caixa ou um popup flutuam sobre a página e não movem nada. Ferramentas de consentimento como a OneTrust e a CookieYes oferecem estes mesmos formatos; o Lighthouse vê o banner delas em cada execução porque arranca sem cookies. Uma barra que tenha obrigatoriamente de ficar acima do cabeçalho deve ter o seu espaço reservado no tema, com a altura que o separador Computed indica na largura de telemóvel:

<div id="promo-slot" style="min-height: 48px"></div>

Para uma barra que só aparece em algumas visitas, deixe-a flutuar ou renderize-a no HTML no servidor. Conteúdo visível gerado por uma tag do Google Tag Manager chega sempre após o first paint: mova-o para o template. No Shopify, uma app que injete um widget, como estrelas de avaliação ou uma barra de avisos, precisa de uma altura definida no contentor que recebe o bloco da app.

CSS que carrega após o first paint

Uma folha de estilos carregada com o truque do media="print", ou adiada ou carregada de forma assíncrona por um plugin de otimização, chega depois de a página estar no ecrã e redimensiona o que já lá está: um cabeçalho que cresce empurra tudo o que estiver abaixo. No plugin, exclua-a da opção que adia o CSS ou que o carrega de forma assíncrona; no tema, carregue-a com um <link rel="stylesheet"> simples no head.

Animações, sliders e blocos renderizados por JavaScript

Estes vêm normalmente do tema, de um plugin ou de uma app: procure aí uma definição. Se não houver nenhuma, envie a um programador o elemento indicado no relatório e o código abaixo.

Uma animação de top, left, height ou margin altera o layout a cada frame. O Lighthouse lista-a como várias linhas curtas sem indicação de causa, e a auditoria "Avoid non-composited animations" sob Diagnostics indica o elemento. Em alternativa, anime a propriedade transform: move apenas os píxeis do elemento e nada ao redor, pelo que o browser não contabiliza qualquer mudança de layout.

.promo { position: fixed; top: 0; left: 0; right: 0;
         transform: translateY(-100%); transition: transform .3s; }
.promo.is-open { transform: translateY(0); }

Um slider mostra os respetivos slides empilhados até o seu script correr; mantenha-o no primeiro slide até o script adicionar a classe de estado pronto (use a do seu próprio slider):

.slider:not(.is-ready) > :not(:first-child) { display: none; }

Um bloco que o JavaScript renderiza após o carregamento, como avaliações ou produtos relacionados, precisa de um contentor vazio na sua altura final ou de ser renderizado no servidor. Para animações no scroll, consulte scroll-triggered animations e CSS transitions.

Mudanças causadas por código que não pode editar

Não é possível alterar o que um criativo de anúncio, uma app sem opção de layout ou o script de um fornecedor inserem. Reserve a altura que normalmente ocupa, posicione-o abaixo do primeiro ecrã ou substitua-o por outro que respeite o seu espaço.

As alterações reduziram o CLS a 0?

Valide a correção no Lighthouse em telemóvel, com o plugin de cache e a CDN limpos. Sem qualquer mudança, o Layout shift culprits surge como aprovado e o CLS fica a 0. Uma gravação no painel Performance, feita uma vez com recarregamento e outra durante o scroll, apresenta a faixa Layout shifts vazia. O CoreDash mostra o novo CLS por elemento a partir das visitas seguintes; o Search Console demora até 28 dias.

Lighthouse na largura de telemóvel na página de receita antes das correções: pontuação 87, CLS 0,241 a laranja, todas as outras métricas a verde e Layout shift culprits a vermelho.

Antes

Lighthouse na largura de telemóvel na mesma página após as correções: pontuação 100, CLS 0 e Layout shift culprits nas auditorias aprovadas.

Depois

Antes e depois das quatro correções: Lighthouse 13.5, telemóvel, throttling simulado.

Algumas mudanças surgem em sítios a que não tem acesso: um espaço de anúncio preenchido pelo parceiro publicitário, uma app que injeta o seu widget, uma mudança que só os visitantes reais veem após fazerem scroll. Numa Core Web Vitals power hour, analisamo-las nos seus field data e numa gravação da sua página, e decidimos que altura atribuir a cada contentor.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

 
Arjen Karel

Precisa de um site mais rápido?

Sou o Arjen e há 17 anos que corrijo sites lentos. Se tem problemas que não consegue resolver sozinho, envie-me o seu URL e falamos.

Envie-me o seu URL
Arjen Karel
Arjen Karel, Consultor de web performance desde 2009

Porque é que o nosso fix não está a funcionar?

Por vezes a CDN ainda serve o HTML antigo, ou o fix foi feito no template de desktop e o mobile usa outro. Envie-me o seu URL e o problema, e respondo com alguns horários. Primeiro analiso os seus field data, depois dedicamos uma hora ao seu site, e no prazo de um dia tem as minhas notas por escrito. 350 € sem IVA.

Envie-me o seu URL

Sem programador para fazer o fix? Faço eu o trabalho, numa cópia do seu site.

Corrigir o Layout shift culprits no Lighthouse e PageSpeed Core Web Vitals Corrigir o Layout shift culprits no Lighthouse e PageSpeed