Pular para o conteúdo

Tecnologia

Core Web Vitals: os três números e o que move cada um

Três siglas, três limiares e uma regra de leitura que quase ninguém aplica. O que muda o número, e o que só parece que muda.

Leandro Bruzaferro5 min de leitura

Core Web Vitals é o nome que o Google deu a três medidas de experiência de carregamento. Elas viraram assunto porque entram na avaliação de página, mas o motivo de olhar para elas é anterior a busca: são as três coisas que fazem alguém desistir antes de ler.

A documentação oficial traz os limiares sem margem para interpretação.

  • LCP, Largest Contentful Paint: o maior elemento visível precisa aparecer em até 2,5 segundos.
  • INP, Interaction to Next Paint: a resposta a uma interação precisa sair em 200 milissegundos ou menos.
  • CLS, Cumulative Layout Shift: o deslocamento acumulado de layout precisa ficar em 0,1 ou menos.

A regra de leitura que muda tudo: percentil 75

Os limiares não valem para a média das visitas. Valem para o percentil 75, separado entre celular e desktop. Traduzindo: três de cada quatro visitas precisam ficar dentro do limite.

O documento que explica como os limiares foram definidos conta o raciocínio: o percentil precisava garantir que a maioria das visitas tivesse a experiência alvo, sem que o resultado fosse distorcido por casos extremos. No percentil 95, uma rede ruim isolada contaminaria a medida; no 75, seriam necessárias 25 de cada 100 visitas fora da curva para mexer no número.

É por isso que otimizar no seu MacBook com fibra não significa nada. O seu percentil 75 é um celular intermediário em rede móvel, e é ele que você precisa imaginar.

LCP: quase sempre é uma imagem

O web.dev é direto sobre onde está o problema: 73% das páginas em celular têm uma imagem como elemento do LCP. Ou seja, na maioria dos sites o número não depende de código, depende de uma foto.

As três alavancas reais, em ordem de retorno:

  1. 01Tornar o recurso do LCP descobrível cedo. Se a imagem principal está atrás de JavaScript, o navegador só descobre que precisa dela depois de baixar e executar o script. Ela precisa estar no HTML.
  2. 02Priorizar o recurso certo e despriorizar o resto. `fetchpriority="high"` na imagem principal, e nada de `loading="lazy"` nela, que é o erro mais comum de quem aplicou lazy loading em tudo de uma vez.
  3. 03Reduzir o peso do arquivo, não a resolução. Formato moderno costuma cortar metade dos bytes com a mesma imagem na tela.

Este site é um exemplo com números conferidos. A capa do artigo que você está lendo virou o elemento do LCP desta página, e a mesma foto pesa 188 KB em JPEG e 78 KB em AVIF. É menos da metade, sem mudar nada do que você vê. O AVIF entra por `<source>` dentro de um `<picture>`, com o JPEG no `<img>` como reserva, porque navegador sem suporte a AVIF não mostra uma imagem pior: não mostra imagem nenhuma.

CLS: é quase sempre falta de dimensão declarada

A mesma página do web.dev traz o segundo número que explica o problema: 66% das páginas têm pelo menos uma imagem sem tamanho definido. Sem `width` e `height`, o navegador não sabe quanto espaço reservar, monta a página sem a imagem e depois empurra tudo para baixo quando ela chega.

Esse empurrão é o CLS. É também a razão de você clicar no botão errado quando um anúncio carrega atrasado, o que liga este assunto diretamente à monetização: layout que se mexe gera clique acidental, e clique acidental é tráfego inválido.

As outras duas causas comuns são fonte que troca e muda a altura da linha, e animação que anima propriedades de layout. Animar `transform` e `opacity` não causa recálculo de layout; animar `height`, `margin` ou `top` causa. Neste site os trilhos animados que aparecem nas páginas de processo usam `scaleY` justamente por isso, e o CLS medido fica em zero.

INP: é o JavaScript no meio do caminho

INP mede quanto tempo a página leva para desenhar algo depois que você toca nela. Quando esse tempo estoura, a causa quase sempre é uma tarefa longa segurando a thread principal enquanto o clique espera a vez.

As recomendações do web.dev vão na mesma direção: quebrar tarefas longas em pedaços, para o navegador conseguir encaixar o trabalho urgente do usuário no meio; evitar JavaScript desnecessário na inicialização; e evitar atualizações de renderização grandes de uma vez.

Vale a observação incômoda: a maior parte do JavaScript que estoura o INP de um site de conteúdo não é do site. É de tag de terceiro. Cada script de analytics, chat, mapa de calor e pixel disputa a mesma thread, e o botão que não responde é a soma de todos eles.

Laboratório e campo medem coisas diferentes

Uma nota que evita muita discussão inútil: rodar o Lighthouse na sua máquina é medição de laboratório, um carregamento simulado em condições fixas. O que entra na avaliação de página é dado de campo, coletado de gente real ao longo do tempo.

Os dois divergem, e é esperado que divirjam. Laboratório serve para diagnosticar e comparar mudanças; campo serve para saber como está. Confundir os dois faz gente comemorar nota alta com usuário real sofrendo, e o contrário também.

Por isso este texto não publica a nota deste site. Ela oscila conforme a máquina que mede, e um número dependente do medidor não descreve a página. Se quiser conferir, rode o PageSpeed Insights neste domínio e olhe o dado de campo, que é o que vale.

O resumo honesto

Core Web Vitals não é assunto de otimização fina. Três decisões resolvem a maior parte: colocar a imagem principal no HTML com prioridade e em formato moderno, declarar dimensão em toda imagem, e cortar o JavaScript que não precisa estar ali.

O resto é ajuste de margem. E se o seu site já faz essas três coisas e continua ruim, o problema provavelmente não é o site: são as tags que alguém foi acrescentando ao longo dos anos e ninguém removeu. É o tipo de coisa que a gente audita antes de propor reescrever qualquer linha.

Fontes

Todas abertas e conferidas antes de entrarem no texto. Se alguma sair do ar, avise pelo contato e a gente corrige.

Conversar

Tem um problema parecido na sua operação?

Se alguma parte disto bateu com o que você está vivendo, manda a situação. A gente responde dizendo o que faria, mesmo quando a resposta é que não é trabalho para a gente.

A gente responde dizendo o que faria, mesmo quando a resposta é que não é trabalho para a gente.