Definición
INP (siglas de Interaction to Next Paint) es una de las tres métricas de Core Web Vitals. Mide cuánto tarda el sitio en responder visualmente a cualquier interacción del usuario (clic, tap, pulsación de tecla) durante toda la sesión.
A diferencia de su predecesora FID (First Input Delay), que solo medía la primera interacción, INP analiza todas las interacciones y reporta la peor (o casi la peor — usa el percentil 98 para descartar valores extremos).
Pasó a ser oficial en marzo de 2024, sustituyendo a FID. Si lees artículos que mencionan FID, están desactualizados.
Cómo funciona
Cada vez que el usuario interactúa con tu web, INP cronometra desde el evento hasta que el siguiente frame se pinta en pantalla mostrando feedback visual. Eso incluye:
- Input delay: tiempo desde el evento hasta que empieza a procesarse (esperando que el main thread esté libre)
- Processing time: tiempo ejecutando los handlers JavaScript
- Presentation delay: tiempo desde que termina el JS hasta que el navegador pinta el nuevo frame
Si haces clic en un botón y aparece un menú al cabo de 600ms, tu INP de esa interacción es 600ms.
Umbrales de Google
| INP | Calificación |
|---|---|
| ≤ 200 ms | Bueno ✅ |
| 200 – 500 ms | A mejorar ⚠️ |
| > 500 ms | Pobre ❌ |
Para aprobar Core Web Vitals, el percentil 75 de tus visitantes reales debe estar ≤ 200ms.
Causas típicas de mal INP
- JavaScript pesado bloqueando el main thread: librerías de 500KB+, bundles sin code-splitting, side-effects síncronos al render
- Event handlers que hacen demasiado: tareas pesadas dentro de
onClicksin trocear - Re-renders excesivos en React/Vue/Svelte tras cada interacción
- Layout thrashing: leer/escribir del DOM en bucle
- Third-party scripts (analytics, chats, ads) ejecutándose sin idle
- CSS pesado con animaciones que bloquean el render
Ejemplo práctico
Un botón "Añadir al carrito" que:
0ms ─ Usuario hace clic
[INPUT DELAY] Main thread ocupado con un render de React
180ms ─ Empieza a procesar el clic
[PROCESSING] handleClick() valida, actualiza estado, llama API mock
320ms ─ Termina el JS, vuelve al navegador
[PRESENTATION] Navegador repinta mostrando "Añadido ✓"
380ms ─ Frame visible
INP de esta interacción = 380ms ❌ Suspende
Optimizaciones aplicables:
- Trocear el handler con
requestIdleCallbackosetTimeout(fn, 0) - Usar
useTransition(React 18+) para marcar updates como no urgentes - Mostrar feedback óptico inmediato (
setLoading(true)) antes de la lógica pesada - Diferir scripts third-party con
loading="lazy"o<script defer>
INP vs FID — qué cambió
| FID | INP | |
|---|---|---|
| Qué mide | Solo primera interacción | Todas las interacciones |
| Componentes | Solo input delay | Input delay + processing + presentation |
| Umbral bueno | 100 ms | 200 ms |
| Fiabilidad | Optimista (solo primer dato) | Realista (peor caso) |
Muchas webs que aprobaban FID suspenden INP. La métrica es más estricta.
Errores comunes
- Optimizar solo el TTI o el FID: ambas son obsoletas o limitadas. Concéntrate en INP directamente.
- Confiar en lab data: Lighthouse simula INP con un cálculo aproximado, pero la métrica oficial usa datos de usuarios reales (CrUX). Pueden diverger mucho.
- Asumir que es problema de tu código: a veces el villano es un script de Google Analytics, Tag Manager, chat de soporte o cookie consent. Audita el third-party.
- Optimizar el primer paint y olvidar las interacciones: una web que carga rápido pero responde lento da peor sensación que una que tarda 100ms más en cargar pero responde instantáneamente.
Cuándo priorizar INP
- Si Search Console muestra INP en rojo en una buena parte del tráfico
- En SPAs con muchas interacciones por sesión (apps, dashboards, e-commerce con filtros)
- Tras añadir librerías UI pesadas o scripts de terceros (re-medir siempre)
- Antes de campañas grandes donde el bounce sería caro