Przejdź do treści
arduralab
·9 min

INP (Interaction to Next Paint) — deep dive 2026

MG
Marcin Godula

Współzałożyciel & Head of SEO/Tech

Specjalista SEO, GEO i web development z ponad 15-letnim doświadczeniem. Pomaga firmom B2B budować widoczność w wyszukiwarkach klasycznych i AI.

INP (Interaction to Next Paint) zastąpił FID w marcu 2024 jako Core Web Vital responsywności. INP mierzy worst-case opóźnienie interakcji w całej sesji — nie tylko pierwszej. Cel <200ms na mobile. Wysokie INP = ranking penalty + frustrated users. W 2026 to jeden z najważniejszych ranking factors, ale w audytach, które robimy, wciąż też najmniej rozumiany — klienci pytają o LCP, prawie nikt nie pyta o INP, dopóki nie pokażemy, gdzie boli.

TL;DR — INP

ElementDetale
Co mierzyCzas od interakcji (kliknięcie) do następnego painta
GraniceGood <200ms, Needs Improvement 200-500ms, Poor >500ms
WprowadzonyMarzec 2024 (zastąpił FID)
Mobile vs desktopMobile 2-3x wyższe INP (słabszy CPU)
Ranking factorTak — Page Experience update
Główne przyczynyHeavy JavaScript, long tasks, inefficient handlers
OptymalizacjaCode splitting, defer, web workers, optimize handlers

Czym INP różni się od FID?

FID (First Input Delay) — deprecated

Mierzył opóźnienie pierwszej interakcji użytkownika. Problem: jeśli pierwszy klik był szybki (50ms), ale każdy następny 800ms — FID nadal pokazywał „good". To była metryka, która pozwalała stronie wyglądać dobrze na papierze, mimo że realny użytkownik po piątym kliknięciu miał już dość.

INP (Interaction to Next Paint) — current

Mierzy interakcje w całej sesji. Bierze 75th percentile (lub max przy <50 interakcji). Pokazuje realny user experience.

Praktyka:

  • FID: 1 measurement
  • INP: aggregated z 10+ interakcji
  • INP > FID typowo (FID was forgiving)

Co to jest „Next Paint"?

User klika button → strona musi:

  1. Process event (event listener fires)
  2. Run JavaScript (callback execution)
  3. Update DOM (state change)
  4. Re-render (browser paints new state)

INP = czas od step 1 do step 4 (next paint po interakcji).

Granice INP

Good (<200ms)

  • Interakcja czuje się instant
  • User nie zauważa opóźnienia
  • Ranking factor passing

Needs Improvement (200-500ms)

  • Interakcja czuje się laggy
  • User zauważa opóźnienie
  • Ranking factor warning

Poor (>500ms)

  • Interakcja czuje się broken
  • User clicka multiple times (więcej events!)
  • Ranking penalty significant

Dlaczego INP jest hard?

Cztery rzeczy sprawiają, że INP jest trudniejsze do ogarnięcia niż LCP czy CLS — i dlatego regularnie widzimy strony, które mają zielone LCP i CLS, a mimo to tracą pozycje.

1. Mobile devices are slower

iPhone 12 vs MacBook M2 — INP 5-10x wyższe na mobile. Devs testują na M2, mobile users sufferują. To najczęstszy powód, dla którego klient jest zaskoczony wynikiem audytu — na jego laptopie strona „działa świetnie".

2. Real user data

Lab tests (Lighthouse) nie capture real INP. CrUX (Chrome User Experience Report) data przeważa.

3. Long tail

INP = worst case. 99% interakcji może być szybkie, 1 slow click rejestruje INP.

4. Third-party scripts

Analytics, chat, ads — często źródło long tasks. Hard to remove (business need). To jest ten rodzaj problemu, gdzie techniczna odpowiedź (usuń skrypt) zderza się z biznesową (marketing potrzebuje danych z tego skryptu) — i trzeba szukać kompromisu, nie tylko fixu w kodzie.

Główne przyczyny wysokiego INP

1. Heavy JavaScript

Główna przyczyna. Frameworks (React, Vue, Angular) + business logic + tracking = 200-500KB+ JS execution.

Fix:

  • Code splitting (load tylko tego co potrzebne)
  • Lazy loading components
  • Tree shaking (usuń unused code)
  • Smaller bundle (Astro, Next.js + RSC)

2. Long tasks (>50ms)

Browser blocks UI gdy JS task running. Long tasks = JS execution longer than 50ms.

Fix:

  • Break long tasks: setTimeout, requestIdleCallback
  • Web Workers dla heavy compute
  • requestAnimationFrame for visual updates

3. Inefficient event handlers

// Złe — heavy work na każdy click
button.addEventListener('click', () => {
  // 200ms of computation
  for (let i = 0; i \< 10000; i++) {
    expensiveOperation();
  }
  updateUI();
});

// Dobre — defer heavy work
button.addEventListener('click', () => {
  // UI feedback immediate
  showLoadingSpinner();
  
  // Heavy work async
  setTimeout(() => {
    for (let i = 0; i \< 10000; i++) {
      expensiveOperation();
    }
    hideLoadingSpinner();
    updateUI();
  }, 0);
});

4. Layout thrashing

Reading + writing DOM in same frame causes forced reflows.

// Złe — thrashing
elements.forEach(el => {
  const height = el.offsetHeight; // read
  el.style.height = height + 10 + 'px'; // write — forces reflow
});

// Dobre — batch reads, then writes
const heights = elements.map(el => el.offsetHeight); // all reads first
elements.forEach((el, i) => {
  el.style.height = heights[i] + 10 + 'px'; // all writes after
});

5. Third-party scripts

Chat widgets, analytics, ads. Often blocked main thread.

Fix:

  • Defer loading (<script defer> lub async)
  • Self-host when possible
  • Replace heavy chat with lightweight alternatives
  • Audit usage — czy używasz wszystko?

6. React synchronous re-renders

Big React tree + frequent state changes = blocking renders.

Fix:

  • React.memo for pure components
  • useMemo / useCallback dla expensive calculations
  • React Concurrent Mode / Suspense (React 18+)
  • Virtualization dla long lists (react-window)

Jak debugować INP

Zanim cokolwiek naprawimy, chcemy zobaczyć konkretną interakcję, która psuje wynik — nie ogólny score, tylko klik, który trwa najdłużej.

1. PageSpeed Wnioski

pagespeed.web.dev → mobile tab. Pokazuje:

  • INP score
  • Interactions causing high INP
  • Recommendations

2. Chrome DevTools — Skuteczność tab

  1. Open DevTools (F12)
  2. Skuteczność tab
  3. Click record
  4. Interact z stroną (10-15 razy różne actions)
  5. Stop recording
  6. Look for Long Tasks (>50ms — orange/red)
  7. Drill into specific task — what's slow?

3. Web Vitals Chrome Extension

Real-time INP w Chrome toolbar. Mierzy actual user interactions na Twojej stronie.

4. Web Vitals JS library

<script type="module">
  import {onINP} from 'https://unpkg.com/web-vitals?module';
  onINP(metric => {
    console.log('INP:', metric.value);
    // Send to analytics
    gtag('event', 'web_vitals', {
      name: 'INP',
      value: metric.value,
    });
  });
</script>

Real User Monitoring (RUM) — capture INP od actual users.

5. CrUX (Chrome User Experience Report)

https://pagespeed.web.dev/

Compare your INP vs competitors using real user data z Chrome.

Strategie optymalizacji INP

Kolejność, w jakiej podchodzimy do tych siedmiu strategii, zależy od tego, co pokazał debugging wyżej — nie warto zaczynać od web workerów, jeśli problemem jest jeden ciężki skrypt analityczny.

Strategy 1: Reduce JavaScript bundle

  • Tree shaking — remove unused exports
  • Code splitting — load chunks per route
  • Bundle analysis (webpack-bundle-analyzer) — co jest big?
  • Replace heavy libraries (moment.js → date-fns, lodash → native)

Strategy 2: Defer non-critical JS

<!-- Defer = wait for HTML parse, then execute in order -->
<script src="/main.js" defer></script>

<!-- Async = execute as soon as loaded -->
<script src="/analytics.js" async></script>

Strategy 3: Web Workers

Heavy compute → separate thread, doesn't block main thread:

// main.js
const worker = new Worker('/heavy-task.js');
worker.postMessage({data: largeArray});
worker.onmessage = (e) => {
  console.log('Result:', e.data);
};

// heavy-task.js
self.onmessage = (e) => {
  const result = expensiveProcessing(e.data.data);
  self.postMessage(result);
};

Strategy 4: Optimize React

  • React 18 + Concurrent rendering
  • React.memo dla components
  • useMemo, useCallback
  • Virtualization dla list (>100 items)
  • Suspense dla data fetching

Strategy 5: Reduce third-party impact

  • Audit third-party scripts (Lighthouse → Third-party usage)
  • Replace heavy with light (e.g. Crisp Chat → custom WhatsApp link)
  • Self-host analytics (server-side tracking)
  • Lazy load chat widgets (only after first scroll)

Strategy 6: Optimize event handlers

  • Throttle / debounce frequent events (scroll, resize)
  • Pasywne event listeners gdzie OK
  • Use onClick per element rather niż delegated parent

Strategy 7: Minimize DOM size

Large DOM (>1500 nodes) = slow layout calculations.

  • Pagination (less items per page)
  • Virtualization
  • Reduce nesting levels

INP w różnych frameworks

Next.js / React

Common INP issues:

  • Large bundle (default 200-500KB JS)
  • Hydration cost
  • Frequent re-renders

Fix:

  • React Server Components (Next.js 13+)
  • Dynamic imports
  • next/script z defer

Astro

Best dla INP — ships zero JS by default. Component „islands" hydrated only when needed. Jeśli klient pyta, jak w ogóle uniknąć problemu z INP zamiast go leczyć, to jest odpowiedź.

WordPress

INP often poor due to:

  • Plugin JS bloat
  • Theme JS
  • Third-party (analytics, social, ads)

Fix:

  • Aggressive lazy loading
  • Caching plugin (WP Rocket)
  • Plugin audit (remove unused)
  • Lighter theme

Vanilla JS

Best control, lowest INP możliwe. Ale wymaga more dev time.

INP optimization checklist

  • Bundle size <300KB JS (gzipped)
  • No JavaScript blocking >50ms tasks
  • Critical path JS deferred or async
  • Third-party scripts lazy loaded
  • Event handlers debounced/throttled gdzie applicable
  • React components memoized
  • Lists virtualized (>100 items)
  • DOM <1500 nodes per page
  • No layout thrashing
  • Web Workers dla heavy compute
  • Mobile-first testing (real devices)
  • RUM monitoring deployed

Najczęstsze błędy w optymalizacji INP

  1. Testing tylko na desktop — mobile dwukrotnie wolniejsze
  2. Lab data only — Lighthouse nie capture real INP
  3. Synchronous heavy compute — blocks main thread
  4. Premature optimization — fix główne problemy first
  5. Removing analytics blindly — utrata data
  6. Brak monitoring — nie wiesz czy się poprawia
  7. Single optimization — cumulative impact = many small fixes

INP a Core Web Vitals overall

INP jest jednym z 3 CWV:

  • LCP (Largest Contentful Paint) — loading speed
  • CLS (Cumulative Layout Shift) — visual stability
  • INP — responsiveness (zastąpiło FID)

Wszystkie muszą passing dla good Page Experience score.

Podsumowanie

INP 2026:

  1. Cel <200ms na 75th percentile mobile
  2. Główna przyczyna — heavy JavaScript blocking main thread
  3. Debug w DevTools — Skuteczność tab + Long tasks
  4. Real User Monitoring — Web Vitals library
  5. Optymalizacje: code splitting, defer, web workers
  6. Mobile-first testing — emulate slow CPU
  7. Continuous monitoring — INP changes z każdym deployment

Z tego, co widzimy w praktyce, INP to metryka, którą klienci najczęściej ignorują aż do momentu, gdy zobaczą, że strona konkurenta reaguje na kliknięcie natychmiast, a ich własna z opóźnieniem. To ranking factor, ale przede wszystkim user experience. Strona z INP 600ms frustruje users, którzy clickają multiple times — zwiększając INP further. Spirala. INP <200ms = smooth UX, retention, konwersje.

Audyt Core Web Vitals + INP — sprawdzimy obecną skuteczność i przygotujemy roadmap optymalizacji.

Chcesz osiągnąć podobne rezultaty? Zamów bezpłatną wycenę.

Pojęcia z tego artykułu

Potrzebujesz pomocy z tym tematem?

Zamów bezpłatny audyt i dowiedz się, jak możemy pomóc Twojej firmie rosnąć w internecie.

Bezpłatna wycena