Journal/INP in 2026: Why Your Site Feels Janky Even When It Looks Fast

INP in 2026: Why Your Site Feels Janky Even When It Looks Fast

PerformanceFront-End CraftWeb Design

INP replaced FID for good reason. Here is how to find and fix the interactions that make portfolio sites feel sluggish, even when the initial load is fast.

INP in 2026: Why Your Site Feels Janky Even When It Looks Fast illustration

The Metric That Changed the Conversation

First Input Delay measured one thing: how long the browser waited before it could start processing your first interaction. It was a queue-depth metric. If the main thread was busy parsing JavaScript when you clicked a button, FID captured that delay. But it told you nothing about what happened next.

Interaction to Next Paint measures the full loop. From the moment you tap, click, or press a key, through JavaScript execution, style recalculation, layout, and paint, all the way to the frame where the visual result appears on screen. And it does not just measure the first interaction. It tracks every interaction on the page and reports the worst one at the 98th percentile.

This matters for portfolio sites because most of them loaded fast and felt slow. FID was green. The hero image arrived quickly. But when you clicked a filter, opened a lightbox, or tried to navigate the menu on mobile, the response was mushy. INP finally gave that mushiness a number.

Why Portfolio Sites Struggle With INP

Static portfolio sites should have an INP advantage. Less JavaScript means less main thread contention. But several common patterns erode that advantage:

Hamburger menu animations. The mobile nav pattern on most studio sites involves toggling a full-screen overlay with a CSS transition. If the toggle handler also manipulates the DOM (adding or removing classes on multiple elements, updating ARIA attributes, trapping focus), the combined work can exceed 200 milliseconds on mid-range mobile devices. The fix is to keep the DOM manipulation minimal, use CSS transitions rather than JavaScript animation, and avoid forcing layout between DOM writes.

Project grid filtering. Many portfolio sites let visitors filter work by category. If this filter removes and re-adds DOM nodes for a grid of 15-30 project cards, each with images and text, the re-render cost is real. Consider using CSS visibility or display toggling instead of removing and recreating nodes. Better yet, use the content-visibility CSS property to let the browser skip rendering for off-screen cards.

Image lightboxes. Clicking a portfolio image to see it full-screen often triggers: create overlay element, load full-resolution image, apply entrance animation, trap keyboard focus. If all of this runs synchronously in a click handler, the frame where the lightbox becomes visible can be delayed significantly.

Scroll-driven animations. CSS scroll-driven animations run off the main thread and are INP-safe. But JavaScript scroll handlers that trigger getBoundingClientRect(), offsetHeight, or getComputedStyle() force layout recalculation on the main thread. On a page with multiple animated sections, this adds up.

Third-party embeds. A Vimeo or YouTube embed on a project page brings its own JavaScript. When a visitor interacts with the embed or with page elements while the embed's scripts are running, INP suffers.

Diagnosing INP Problems

The diagnostic toolchain has matured considerably since INP became a Core Web Vital:

Chrome DevTools Interactions track. Open the Performance panel, start a recording, perform interactions on your site, then look at the Interactions track. Each interaction shows the input delay, processing time, and presentation delay as separate segments. The longest segment tells you where to focus.

Long Animation Frames API. This browser API lets you programmatically detect frames that took longer than 50 milliseconds. You can log these in your analytics to find which pages and interactions are problematic in the field, not just in lab testing.

Web Vitals library attribution build. The web-vitals library has an attribution mode that tells you exactly which interaction caused the reported INP value, including the target element and the event type. Deploy this to production to get real user interaction data.

PageSpeed Insights. The field data section shows INP at the origin level and per-URL level. If your origin INP is marginal (150-200ms), investigate the worst individual pages.

The Fix Playbook

1. Reduce JavaScript execution in event handlers

The single most impactful change for INP is doing less work in response to user actions. Audit every click, keydown, and pointer handler on your site. For each one, ask: does all of this work need to happen synchronously before the next paint?

Common opportunities:

  • Defer analytics event tracking with requestIdleCallback or setTimeout
  • Move DOM measurement (reading layout properties) before DOM mutation (writing layout properties) to avoid forced synchronous layout
  • Use CSS transitions for visual state changes instead of JavaScript-driven animation
  • Pre-compute values during idle time rather than on interaction

2. Break up long tasks

If an interaction handler must do significant work, break it into smaller chunks using scheduler.yield() (available in Chrome) or setTimeout(fn, 0) as a fallback. This gives the browser a chance to paint between chunks, which reduces the perceived delay even if total processing time is the same.

3. Optimize CSS selector complexity

Style recalculation is part of INP. If your CSS has deeply nested selectors, expensive pseudo-classes like :has() on large DOM trees, or broad universal selectors, style recalc can take significant time after DOM changes. Keep selectors flat and specific.

4. Minimize layout thrashing

Layout thrashing happens when JavaScript alternates between reading and writing layout properties in a loop. Each read forces the browser to recalculate layout to return an accurate value. Batch all reads together, then batch all writes together.

A classic example on portfolio sites: measuring the position of multiple elements to decide where to place a tooltip or popover. Read all positions first, store them, then apply all positioning changes at once.

5. Audit third-party scripts

Every third-party script that registers event listeners or runs periodic tasks is a potential INP contributor. Use the Performance panel to identify long tasks that originate from third-party code. Consider lazy-loading non-critical third-party scripts until after the user has interacted with your own content.

INP Budgets for Different Page Types

Not all pages on a portfolio site have the same interaction profile:

Home page: Usually minimal interactions beyond scrolling and navigation clicks. Budget: 100ms. Should be easy to hit.

Work listing page: May have category filters and hover interactions. Budget: 150ms. Watch the filter handler.

Project detail page: May have image lightboxes, video embeds, and scroll animations. Budget: 150ms. This is where most INP failures occur.

Contact or enquiry page: Form interactions with validation. Budget: 100ms. Keep validation lightweight and avoid re-rendering the entire form on each keystroke.

As we covered in the Core Web Vitals playbook, the official threshold is 200ms. But aiming for 150ms gives you headroom for the variance between lab testing and real field conditions on slower devices.

The Hardware Reality

Your development machine is not your users' device. A 2024 MacBook Pro processes JavaScript roughly 4 to 6 times faster than a mid-range Android phone from the same year. An interaction handler that takes 40 milliseconds on your machine can take 200 milliseconds on a visitor's phone.

Test on real mid-range hardware, or use Chrome DevTools CPU throttling set to 4x or 6x slowdown. This does not perfectly simulate real device behavior, but it exposes problems that are invisible at full speed.

When INP Does Not Matter

If your portfolio site is truly static with no JavaScript interactions beyond native browser behavior (link clicks, form submissions, scrolling), your INP will be excellent by default. Do not add complexity to optimize a metric that is already passing.

The sites that need to worry about INP are the ones that have added client-side interactivity: filters, animations, lightboxes, video players, and dynamic content loading. If you have those features, INP is the metric that tells you whether they feel responsive or sluggish.

FAQ

Does server-side rendering help with INP?

Not directly. INP measures post-load interaction responsiveness, not initial rendering speed. SSR helps LCP and TTFB. INP depends on what happens after the page is interactive.

Can CSS-only interactions cause INP problems?

Pure CSS transitions and animations run on the compositor thread and do not affect INP. But CSS properties that trigger layout (width, height, top, left, margin) can cause main-thread work during transitions. Stick to transform and opacity for smooth, INP-safe animations.

How do I track INP in production?

Use the web-vitals JavaScript library with the attribution build. Send the data to your analytics provider. Monitor the p75 value weekly and investigate spikes.

The Bottom Line

INP is the metric that bridges the gap between "looks fast" and "feels fast." On portfolio sites, the fixes are usually about removing unnecessary JavaScript work from interaction paths rather than optimizing heavy computation. Less is genuinely more here. The fastest interaction handler is the one that does not exist.


Continue Reading

All journal entries