Lighthouse

CLS no WordPress: imagem sem width e height pulando a página no mobile

O Lighthouse aponta Image elements do not have explicit width and height e, no celular, o texto desce de repente quando a foto termina de carregar. Em quase todo tema que eu abro a causa é a mesma: um <img> montado na mão dentro do template, com a URL saindo de get_the_post_thumbnail_url().

Essa função devolve só a URL, mais nada. Sem os atributos width e height o navegador não tem como reservar o espaço antes do download: ele renderiza o texto colado e empurra tudo pra baixo depois. Esse empurrão é o CLS.

Deixe o WordPress escrever as dimensões

Troque a tag manual por wp_get_attachment_image(). Ela lê os metadados do anexo e devolve width, height, srcset e sizes prontos:

<?php
echo wp_get_attachment_image(
    get_post_thumbnail_id( get_the_ID() ),
    'large',
    false,
    array( 'class' => 'card-thumb' )
);

No upload o WordPress grava largura e altura reais de cada tamanho em _wp_attachment_metadata, e é de lá que a função tira os números. Com os dois atributos no HTML o navegador já segura o buraco do tamanho certo. Dentro do loop, the_post_thumbnail( 'large' ) faz o mesmo serviço.

Uma coisa que eu não passo mais no array de atributos: 'loading' => 'lazy'. Desde a 6.3 quem decide loading e fetchpriority é a wp_get_loading_optimization_attributes(), e forçar lazy marca a imagem como fora da viewport. Na primeira imagem da página isso tira o fetchpriority="high" e piora o LCP enquanto você conserta o CLS.

A armadilha da imagem esmagada

Agora o height virou um número fixo no HTML. Se o layout for fluido, a largura encolhe no celular e a altura não acompanha, deixando a foto achatada. O par que resolve mora no style.css do tema:

.card-thumb {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

O height: auto devolve a proporção pro CSS sem apagar os atributos que o navegador usou pra reservar o espaço, e o aspect-ratio só vale enquanto a altura estiver em auto. Rode o Lighthouse em modo mobile depois de publicar: o aviso some e o CLS cai junto.

Se travou nisso e precisa de ajuda, me chama aqui.

Post Recentes

wp_postmeta lento: índice em meta_key e meta_value para meta_query

Listagem de CPT com meta_query que demora segundos: veja o EXPLAIN da query do WP_Query e o índice composto em…

20 horas atrás

WP-Cron travado: eventos agendados que não rodam no WordPress 6.9

Post com Perdeu o agendamento e backup que não roda há dias: inspecione a fila do WP-Cron, apague a trava…

1 dia atrás

Desligar o AMP no WordPress 6.9: redirect do /amp/ sem perder tráfego

Como aposentar o plugin AMP sem transformar centenas de URLs /amp/ indexadas em 404: o rewrite 301 no nginx, a…

2 dias atrás

Redis OOM Magento 2: ajustar a maxmemory-policy e separar os bancos

A loja cai com OOM command not allowed when used memory > maxmemory: ajuste a maxmemory-policy do Redis e separe…

2 dias atrás

Checkbox de privacidade no checkout do WooCommerce: texto e registro do aceite

Adicione a caixa de aceite no checkout do WooCommerce e grave data e versão da política como meta do pedido,…

3 dias atrás

json_validate no PHP 8.3: conferir se o JSON é válido sem decodificar

A função json_validate do PHP 8.3 diz se a string é JSON válido sem montar array nem objeto. Serve para…

3 dias atrás