icardb
Core Web Vitals na prática: LCP, INP e CLS medidos e corrigidos
Voltar para artigosPROGRAMAÇÃO

Core Web Vitals na prática: LCP, INP e CLS medidos e corrigidos

Por Lucas Mendes 7 min de leitura

Core Web Vitals são as três métricas de experiência que o Google usa como sinal de ranqueamento: LCP (velocidade de carregamento), INP (responsividade a interações) e CLS (estabilidade visual). O detalhe que muita gente perde: a avaliação usa dados de usuários reais (CrUX), não o score sintético do Lighthouse no seu notebook. Este artigo mostra como medir corretamente e como corrigir cada métrica.

As três métricas e seus limites

MétricaO que medeBomRuimAvaliado em
LCP — Largest Contentful PaintTempo até o maior elemento visível renderizar≤ 2,5 s> 4,0 s75º percentil
INP — Interaction to Next PaintLatência da pior interação da visita≤ 200 ms> 500 ms75º percentil
CLS — Cumulative Layout ShiftSoma dos deslocamentos inesperados de layout≤ 0,1> 0,2575º percentil

INP substituiu o FID como métrica oficial em março de 2024. Diferente do FID (só o primeiro clique), o INP observa todas as interações da visita — é uma métrica bem mais exigente.

Medindo: dados de campo versus dados de laboratório

PageSpeed Insights mostra as duas fontes: 'dados reais de usuários' (CrUX, o que vale para ranqueamento) e 'diagnóstico de laboratório' (Lighthouse simulado, útil para debug). Para sites com pouco tráfego — sem dados CrUX próprios — o caminho é medir você mesmo com a biblioteca oficial web-vitals:

ts
// npm install web-vitals
import { onLCP, onINP, onCLS } from "web-vitals";

function enviar(metrica: { name: string; value: number; rating: string }) {
  // beacon: sobrevive ao fechamento da página
  navigator.sendBeacon(
    "/api/metricas",
    JSON.stringify({
      nome: metrica.name,
      valor: metrica.value,
      avaliacao: metrica.rating, // "good" | "needs-improvement" | "poor"
      pagina: location.pathname,
    })
  );
}

onLCP(enviar);
onINP(enviar);
onCLS(enviar);

Corrigindo LCP

O LCP divide-se em quatro fases: TTFB, carregamento do recurso, atraso de renderização e o paint em si. As causas mais comuns, em ordem de frequência:

  1. Imagem hero sem prioridade: adicione fetchpriority='high' e preload; nunca lazy-load na imagem LCP.
  2. CSS/JS bloqueante: inline do CSS crítico e defer no restante.
  3. TTFB alto: cache na borda (CDN), SSR/streaming e otimização de queries no servidor.
  4. Fontes atrasando texto: font-display: swap e preload das fontes principais.
html
<!-- Imagem LCP com prioridade máxima -->
<img src="/hero.avif" alt="Painel do produto" fetchpriority="high" width="1200" height="630" />

<!-- Ou via preload quando é background-image -->
<link rel="preload" as="image" href="/hero.avif" fetchpriority="high" />

Corrigindo INP

INP ruim quase sempre significa main thread ocupada com JavaScript: handlers longos, renderizações pesadas síncronas ou hidratação gigantesca. As técnicas que funcionam: quebrar tarefas longas (>50 ms) cedendo ao event loop, adiar trabalho não-crítico e reduzir o JS enviado.

ts
// Quebrando uma tarefa longa para a UI responder entre pedaços
async function processarItens(itens: Item[]) {
  for (const item of itens) {
    processar(item);
    // cede a main thread: permite paint e input entre iterações
    await new Promise((r) => setTimeout(r, 0));
  }
}

// Trabalho não urgente fora do caminho crítico de interação
import { startTransition } from "react";
function onFiltroChange(valor: string) {
  setTextoBusca(valor); // urgente: atualiza o input
  startTransition(() => setResultados(filtrar(valor))); // pode esperar um frame
}

Corrigindo CLS

Layout shift é sempre um elemento que aparece ou muda de tamanho depois do render inicial, empurrando conteúdo. As três fontes clássicas e suas correções:

  • Imagens sem dimensão: sempre declare width e height (ou aspect-ratio) — o browser reserva o espaço antes de baixar a imagem.
  • Anúncios e embeds: reserve um contêiner com min-height fixo, mesmo que o anúncio falhe.
  • Fontes com métricas diferentes: use font-display: swap com fonte fallback ajustada (size-adjust) ou preload para trocar antes do primeiro paint.
css
/* Reservando espaço sem conhecer a altura exata */
img { width: 100%; height: auto; aspect-ratio: 16 / 9; }

/* Contêiner de anúncio com espaço garantido */
.slot-anuncio { min-height: 250px; }

Não otimize contra o Lighthouse local. Um LCP de 1,2 s na sua máquina com cache quente diz pouco; o 75º percentil de usuários reais em celulares médios com 4G é o número que importa. Instrumente RUM primeiro, otimize depois.

Conclusão

Core Web Vitals não são um projeto único, são um regime contínuo: meça com dados reais, ataque a fase dominante de cada métrica (TTFB e prioridade de recursos no LCP, main thread no INP, espaço reservado no CLS) e proteja o resultado com budgets de performance no CI. Sites que tratam performance como feature permanente raramente precisam de 'projetos de otimização' emergenciais.

Perguntas frequentes

+Core Web Vitals realmente afetam o ranqueamento?

Sim, são um sinal confirmado de page experience, mas o Google é explícito: relevância de conteúdo pesa muito mais. Pense nos Vitals como critério de desempate e fator de conversão — páginas rápidas retêm mais usuários — não como atalho de SEO.

+Meu Lighthouse é 95 mas o CrUX está 'ruim'. Por quê?

O Lighthouse roda em condições simuladas na sua máquina; o CrUX reflete usuários reais com dispositivos e redes heterogêneas no 75º percentil. Dispositivos Android de entrada e redes 4G instáveis puxam a média para baixo. Otimize contra os dados de campo.

+Lazy-load de imagens ajuda ou atrapalha?

Ajuda em tudo abaixo da dobra; atrapalha no elemento LCP. A regra: loading='lazy' nunca na imagem hero, e fetchpriority='high' nela.

+INP alto só em páginas com muito JavaScript?

Predominantemente sim. As causas típicas são handlers de evento longos, re-renderizações grandes síncronas e bundles pesados demais na hidratação. Code splitting agressivo e quebra de tarefas longas resolvem a maioria dos casos.

Fontes consultadas

Revisão editorial: publicado em . Última revisão em . Conteúdo educativo, sem patrocínio das ferramentas citadas.

Crédito da imagem: Foto: Lucas Mendes / Gerado por IA (Licença Editorial)

Leia também