Na atualização de março de 2026, o Google apertou o threshold do LCP (Largest Contentful Paint) de 2,5s para 2,0s. Para sites que estavam confortavelmente no verde com 2,3s, a mudança foi brutal — foram para vermelho da noite para o dia. Junto com isso, INP (Interaction to Next Paint) substituiu definitivamente o FID como métrica de responsividade.
Thresholds atuais de 2026: LCP bom < 2,0s (era 2,5s), INP bom < 200ms, CLS bom < 0,1. Fonte: Google Search Central Documentation, atualizado em março de 2026.
Por que o LCP ficou mais difícil
LCP mede quanto tempo leva para o maior elemento visível na viewport ser renderizado. Na maioria dos sites, esse elemento é uma imagem hero ou o H1 principal. O Google justificou o novo threshold com dados do Chrome UX Report mostrando que redes móveis melhoraram significativamente — 2,0s é realista para 75% dos usuários em 2026.
INP: a métrica que mais derruba sites React
INP mede a latência de todas as interações do usuário — não só a primeira como o FID fazia. Para sites React, INP é traiçoeiro: um evento onClick que dispara um setState que re-renderiza 50 componentes pode facilmente passar de 500ms. O threshold de 200ms é exigente.
// Medindo INP no seu app React
import { onINP } from "web-vitals";
onINP(({ value, rating, entries }) => {
// rating: 'good' | 'needs-improvement' | 'poor'
if (rating !== "good") {
// entries mostra qual interação causou o problema
const worstEntry = entries.reduce((a, b) =>
a.duration > b.duration ? a : b
);
console.warn("INP ruim:", {
duration: value,
element: worstEntry.target,
type: worstEntry.name, // 'click', 'keydown', etc.
});
}
}, { reportAllChanges: true });Padrões para corrigir INP em React
- useTransition: marque atualizações de estado não-urgentes como transição — React as adia sem bloquear a interação
- useDeferredValue: para buscas e filtros, defira o valor que aciona re-renders pesados
- Virtualization: listas longas (>100 itens) precisam de virtualização — use tanstack/virtual
- Evite re-renders em cascata: useCallback + useMemo onde o profiler mostrar gargalos reais, não preventivamente
- Quebre handlers grandes: divida onClick em microtasks com scheduler.yield() (API experimental Chrome 2026)
// useTransition para manter INP bom em filtros
import { useTransition, useState } from "react";
function ProductFilter({ products }) {
const [filter, setFilter] = useState("");
const [isPending, startTransition] = useTransition();
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
// Atualização do input: urgente (sem transição)
const value = e.target.value;
// Filtragem da lista: não-urgente (pode esperar)
startTransition(() => {
setFilter(value);
});
};
const filtered = products.filter(p =>
p.name.toLowerCase().includes(filter.toLowerCase())
);
return (
<>
<input onChange={handleChange} />
<div style={{ opacity: isPending ? 0.7 : 1 }}>
{filtered.map(p => <ProductCard key={p.id} product={p} />)}
</div>
</>
);
}Ferramentas de medição em 2026
Para medir Core Web Vitals em campo (dados reais de usuários): Google Search Console (gratuito, 28 dias de histórico), biblioteca web-vitals (npm, reporta para seu analytics), e PageSpeed Insights com dados do Chrome UX Report. Para lab (dados sintéticos): Lighthouse no DevTools, WebPageTest para comparações detalhadas. O Google recomenda priorizar dados de campo sobre lab.
O CrUX (Chrome UX Report) agora tem granularidade por segmento de dispositivo — você pode ver CWV separados por mobile, tablet e desktop. Útil para identificar se o problema é específico de um segmento.