Skip to main content
Free Consultation

How to Improve INP: 9 Powerful Fixes for JavaScript and Long Tasks

Introduction

How to Improve INP starts with finding the work that prevents a page from responding quickly when someone clicks, taps, or types. Heavy JavaScript, expensive event handlers, long tasks, and excessive main-thread activity can delay the next visual update after an interaction. By measuring interaction latency, reducing unnecessary processing, splitting long tasks into smaller units, and updating the interface efficiently, developers can improve responsiveness and create a smoother user experience. A page can load quickly and still feel frustratingly slow when someone tries to use it.

A menu takes a moment to open. A filter responds late. A button appears to ignore the first click. A search field freezes while suggestions are generated.

These are responsiveness problems, and JavaScript is often involved.

But saying “JavaScript is slow” is too broad to be useful.

The delay can come from an event handler doing too much work, a long task occupying the main thread, expensive DOM changes, forced layout calculations, rendering work, or third-party code competing for CPU time.

Improving Interaction to Next Paint (INP) therefore requires more than minifying JavaScript or making a bundle smaller.

The practical objective is simple:

When a user interacts with the page, the browser should have enough time to respond instead of being buried under unrelated work.

This guide explains how to find that work and reduce it.

How to improve INP with 9 powerful fixes for JavaScript performance, long tasks, slow interactions, and better website responsiveness.

Quick Answer

To improve INP:

  1. Identify the interactions contributing to poor INP.
  2. Find long tasks and expensive JavaScript on the main thread.
  3. Keep event handlers small and focused.
  4. Break large pieces of work into smaller tasks.
  5. Avoid unnecessary DOM updates.
  6. Reduce forced synchronous layout and style calculations.
  7. Move suitable non-UI work away from the main thread.
  8. Delay non-essential JavaScript.
  9. Reduce third-party scripts and their execution cost.
  10. Avoid doing expensive work synchronously during user interactions.
  11. Test real interactions rather than optimizing JavaScript only by file size.
  12. Verify improvements in both lab tools and field data.

The goal is not simply to reduce JavaScript kilobytes.

The goal is to reduce the amount of work the browser has to perform before it can present the next visual update after an interaction.

What Actually Makes INP Poor?

An interaction can be thought of as having three broad stages:

Input delay → Processing time → Presentation delay

The browser first needs an opportunity to respond to the interaction.

Then the relevant event handlers execute.

Finally, the browser needs to perform the work required to update the page and present the result.

A delay in any of these stages can contribute to a slow interaction.

JavaScript commonly affects the processing stage, but it can also contribute to input delay when other JavaScript is occupying the main thread.

Rendering and layout work can contribute to the final stage.

This is why simply looking for a single “slow function” is not always enough.

Why JavaScript Often Causes INP Problems

JavaScript runs on the browser’s main thread in many common web applications.

The same thread is responsible for important browser work such as:

  • Processing JavaScript
  • Handling user input
  • Calculating styles
  • Performing layout
  • Updating the page
  • Painting

When too much work is scheduled at once, interaction can wait.

Imagine a visitor clicks a menu button at exactly the moment a large JavaScript task is running.

The click has happened.

But the browser cannot immediately execute the menu’s event handler because the main thread is occupied.

The user experiences that as a delayed response.

This is why reducing unnecessary main-thread work can be more important for INP than simply reducing the number of JavaScript files.

Long Tasks: A Major Warning Sign

A long task is a task that occupies the main thread for more than 50 milliseconds.

That does not mean every long task automatically creates a poor INP.

But long tasks are important because they can prevent the browser from responding promptly to user input.

For example:

JavaScript task

████████████████████████████████████

                                  ↑

                            User clicks

If the click occurs while the main thread is busy, the interaction may have to wait.

A page containing many long tasks has fewer opportunities to respond quickly.

What Creates Long Tasks?

Common sources include:

  • Large JavaScript execution
  • Complex calculations
  • Parsing large data sets
  • Processing large arrays
  • Expensive framework updates
  • Rendering large DOM trees
  • Third-party scripts
  • Hydration work
  • Client-side application startup
  • Large libraries doing unnecessary work

The solution is not always “remove JavaScript.”

Often the better solution is to break expensive work into smaller pieces or move non-critical work away from the interaction path.

Don’t Confuse Total JavaScript With Interaction Cost

A page may download 500 KB of JavaScript and have excellent responsiveness.

Another page might download only 150 KB and still have poor INP because one interaction triggers an expensive operation.

File size matters, but it is not the same thing as execution cost.

For INP, investigate:

  • What happens when the user interacts?
  • How much JavaScript executes?
  • How much DOM work follows?
  • How much layout and rendering occurs?
  • What else is occupying the main thread?

A smaller bundle can help, but it is not the finish line.

Optimize Event Handlers

An event handler is code that responds to an event such as:

  • Click
  • Pointer interaction
  • Keyboard input
  • Touch interaction
  • Form input
  • Selection changes

A handler should generally do only the work required to respond to that interaction.

Consider a search box.

A poorly designed input handler might:

  1. Read the entire product catalog.
  2. Filter thousands of records.
  3. Sort the results.
  4. Rebuild a large section of the DOM.
  5. Measure several elements.
  6. Trigger additional layout calculations.
  7. Update multiple components.

All of that can happen because the user typed one character.

That is a poor interaction architecture.

A better implementation might:

  • Debounce appropriate searches
  • Keep the immediate UI update small
  • Avoid rebuilding unrelated DOM
  • Process expensive data separately
  • Cache repeated calculations
  • Update only the necessary elements

The user should not have to wait for work that has nothing to do with the immediate response.

Keep the First Response Small

An interaction often has a visible first step.

For example:

User clicks menu → menu opens

The menu opening should not have to wait for unrelated work such as:

  • Analytics processing
  • Large data transformation
  • Recommendation calculations
  • Non-critical component initialization
  • Background DOM updates

Separate the immediate visual response from secondary work whenever the architecture allows it.

This is one of the most useful principles for improving perceived responsiveness.

Break Up Long Tasks

Suppose a function performs a large amount of work:

processEverything();

If processEverything() occupies the main thread for hundreds of milliseconds, user interactions can become unresponsive.

One approach is to divide the work into smaller chunks.

Conceptually:

Large task

████████████████████████████████

becomes

Task  Task  Task  Task  Task

███   ███   ███   ███   ███

Between smaller tasks, the browser gets opportunities to process pending input and rendering work.

Modern browser scheduling APIs can help with this kind of cooperative scheduling.

For example, appropriate work can sometimes be scheduled using APIs such as scheduler.postTask() where browser support and application requirements make it suitable.

The exact implementation depends on the application.

The principle is more important:

Do not monopolize the main thread when the browser needs to respond to the user.

Use requestAnimationFrame() for Visual Updates

When JavaScript needs to update visual state in response to animation or interaction, requestAnimationFrame() can help coordinate updates with the browser’s rendering cycle.

For example:

requestAnimationFrame(() => {

  element.classList.add(“active”);

});

This does not magically make expensive code fast.

It is useful when you need to schedule visual updates in a way that aligns with rendering.

Do not use it as a general replacement for every asynchronous operation.

Avoid Forced Synchronous Layout

One subtle source of performance problems occurs when JavaScript changes the DOM and then immediately asks the browser for layout information.

For example:

element.style.width = “500px”;

const width = element.offsetWidth;

The browser may need to calculate layout before returning the requested value.

If code repeatedly alternates between:

write → read → write → read

it can create expensive layout work.

This pattern is sometimes described as layout thrashing.

A better approach is often to group reads and writes rather than constantly switching between them.

For example:

Read required measurements

↓

Perform updates

↓

Allow browser to render

The exact optimization depends on the code, but the underlying principle is consistent:

Avoid forcing the browser to repeatedly recalculate layout when it could do the work more efficiently.

Reduce Unnecessary DOM Work

A large DOM does not automatically mean poor INP.

The problem occurs when interactions trigger expensive operations across that DOM.

Examples include:

  • Rebuilding large lists
  • Changing hundreds of nodes
  • Updating unnecessary components
  • Recalculating styles across large sections
  • Rendering hidden content unnecessarily
  • Replacing entire containers when only one element changed

If a button changes one label, there may be no reason to rebuild an entire page section.

Keep updates as targeted as possible.

Be Careful With Framework Rendering

React, Vue, Angular, and other frameworks can simplify application development, but they do not remove browser performance constraints.

An interaction can still trigger:

  • Component rendering
  • State propagation
  • DOM reconciliation
  • Layout
  • Painting
  • JavaScript execution

When a framework application has poor INP, investigate what happens during the actual interaction.

Look for:

  • Excessive component updates
  • Large render trees
  • Unnecessary state changes
  • Expensive computations during render
  • Large lists
  • Repeated calculations

Framework-specific optimizations can help, but the diagnosis should begin with the work actually appearing in the performance trace.

Large Lists Can Hurt Interaction Performance

Consider a page displaying 5,000 records.

A filter interaction that causes all 5,000 items to be processed and rendered may become expensive.

Possible solutions include:

  • Pagination
  • Virtualization
  • Incremental rendering
  • More efficient filtering
  • Cached calculations
  • Server-side filtering
  • Smaller DOM representations

The best solution depends on the application.

The key is to avoid doing substantially more work than the user needs for the current interaction.

Move Suitable Work Off the Main Thread

Some calculations do not need direct access to the DOM.

Examples might include:

  • Large data transformations
  • Complex calculations
  • Parsing substantial data
  • Image or file processing
  • Computational operations

For suitable workloads, Web Workers can move JavaScript processing away from the main thread.

A simplified example:

const worker = new Worker(“/worker.js”);

worker.postMessage(data);

worker.onmessage = (event) => {

  updateUI(event.data);

};

The worker does not directly manipulate the page’s DOM.

Instead, it performs the calculation and sends the result back.

This can help keep the main thread available for user interactions.

Workers are not a solution for every problem. Sending large amounts of data between the main thread and a worker also has costs.

Use them when the work is sufficiently expensive and independent from direct DOM access.

Third-Party JavaScript Can Affect INP

Your own code may not be responsible for every long task.

Third-party scripts can perform substantial work on the page.

Examples include:

  • Analytics
  • Advertising
  • Chat widgets
  • Social embeds
  • A/B testing
  • Heatmaps
  • Marketing platforms
  • Customer-support tools

A third-party script can run while a visitor is trying to interact with your page.

That creates competition for the same main-thread resources.

Review third-party scripts with the same questions you apply to first-party code:

  • Is it necessary?
  • Is it loaded on every page?
  • Does it need to initialize immediately?
  • Can it be delayed?
  • Can it load only after interaction?
  • Is its functionality duplicated elsewhere?

Reducing unnecessary third-party execution can improve responsiveness without changing your application’s core code.

Event Delegation Can Reduce Unnecessary Handlers

Pages with large numbers of interactive elements sometimes attach individual event handlers to every element.

For example, a list containing hundreds of items may create hundreds of listeners.

Event delegation can allow a parent element to handle events from its children.

Conceptually:

list.addEventListener(“click”, (event) => {

  const item = event.target.closest(“.item”);

  if (!item) return;

  // Handle interaction

});

This can simplify event management and reduce some overhead.

However, event delegation is not a magic INP fix.

If the delegated handler performs expensive work, the interaction can still be slow.

Focus on the work performed in response to the event.

Debouncing and Throttling: Useful, but Not Interchangeable

High-frequency events such as input, scrolling, and pointer movement can trigger large amounts of work.

Two common techniques are debouncing and throttling.

Debouncing

Debouncing waits until events stop occurring for a period before running the expensive operation.

This can be useful for:

  • Search suggestions
  • Validation
  • Filtering

For example, instead of running an expensive search for every keystroke, the application can wait briefly until the user pauses.

Throttling

Throttling limits how frequently a function can run.

This can be useful when updates need to happen periodically during continuous activity.

For example:

100 events

↓

only process a controlled number of updates

Neither technique should be used blindly.

If a visible interaction needs an immediate response, excessive debouncing can make the interface feel slower rather than faster.

Avoid Unnecessary Work During Clicks

A common architecture problem looks like this:

Click

 ↓

Update UI

 ↓

Save analytics

 ↓

Recalculate data

 ↓

Render recommendations

 ↓

Update unrelated components

 ↓

Send network request

The user may only care about the first step.

Separate the immediate response from secondary work whenever possible.

For example:

Click

 ↓

Immediate UI update

 ↓

Return control to browser

 ↓

Secondary work

The details depend on the application, but this separation can make interactions feel dramatically more responsive.

How to Find the Interaction Causing Poor INP

If field data reports poor INP, do not guess which button is responsible.

Use interaction data where available to identify the relevant element and page state.

Then reproduce the interaction in a controlled environment.

For example:

  1. Open the affected page.
  2. Start a performance recording.
  3. Perform the same interaction.
  4. Stop the recording.
  5. Locate the interaction in the timeline.
  6. Inspect the JavaScript tasks around it.
  7. Look for long tasks.
  8. Inspect style, layout, and rendering work.
  9. Identify the expensive operation.
  10. Change one thing.
  11. Record the interaction again.

This turns INP optimization into a debugging exercise rather than a collection of guesses.

What to Look for in a Performance Trace

When investigating an interaction, pay attention to:

Long JavaScript tasks

Was the main thread occupied for a long period?

Event handler execution

How much work happened directly because of the interaction?

Forced layout

Did JavaScript trigger expensive style or layout calculations?

DOM updates

How many elements changed?

Rendering

Did the interaction trigger substantial paint or compositing work?

Other simultaneous work

Was unrelated JavaScript executing at the same time?

This broader view matters because the code responsible for an interaction may not be the only thing delaying its visual response.

A Practical INP Optimization Workflow

Step 1: Measure

Start with field data when available.

Find out whether the problem is widespread or limited to a particular page, template, device group, or interaction.

Step 2: Identify the interaction

Determine which interaction is contributing to the poor experience.

Step 3: Reproduce it

Use browser developer tools to record the interaction.

Step 4: Find long tasks

Look for main-thread tasks that overlap the interaction.

Step 5: Inspect the handler

Determine what the event handler actually does.

Step 6: Reduce immediate work

Remove unnecessary calculations, DOM updates, and secondary processing from the interaction path.

Step 7: Break up expensive work

Split large tasks into smaller chunks when appropriate.

Step 8: Move suitable computation

Consider Web Workers for expensive calculations that do not need direct DOM access.

Step 9: Review third parties

Check whether external scripts are competing for main-thread time.

Step 10: Measure again

Compare the interaction before and after the change.

Step 11: Validate in the field

Lab improvements are useful, but real-user data is what ultimately tells you whether the experience improved for your audience.

WordPress: Improving INP

On WordPress, poor INP can come from a combination of:

  • Theme JavaScript
  • Page-builder code
  • Plugins
  • Third-party scripts
  • Large DOM structures
  • Interactive widgets
  • Sliders
  • Popups
  • Filters
  • Search functionality

Start with the actual interaction rather than disabling plugins randomly.

For example, if opening a mobile navigation menu takes 500 milliseconds, investigate what happens when the menu button is pressed.

Perhaps the handler:

  • Recalculates a large layout
  • Triggers several components
  • Loads additional JavaScript
  • Runs tracking code
  • Changes many DOM nodes

The right fix depends on the trace.

Removing an unrelated plugin simply because it is present may not address the real problem.

Common INP Optimization Mistakes

Minifying JavaScript and expecting INP to disappear

Minification reduces source size but does not automatically eliminate expensive execution.

Focusing only on bundle size

A small script can still perform expensive work.

Breaking every task into tiny tasks

Excessive scheduling can introduce overhead and make code more complicated.

Break up genuinely expensive work where it improves responsiveness.

Debouncing everything

Too much delay can make an interface feel unresponsive even if the performance trace looks cleaner.

Moving every script to a Web Worker

Workers cannot directly manipulate the DOM and are not suitable for every workload.

Optimizing only lab data

A synthetic interaction may not represent the interactions real users experience.

Ignoring third-party code

External JavaScript can consume the same main-thread time as your own code.

Rebuilding large sections of the DOM

Small UI changes should not require unnecessary large-scale updates.

Chasing a perfect INP number

The objective is a responsive experience, not a benchmark score at any cost.

INP Targets

The current INP thresholds are:

INPRating
200 ms or lessGood
More than 200 ms to 500 msNeeds improvement
More than 500 msPoor

INP is evaluated using real interaction behavior and reported at the 75th percentile when assessing Core Web Vitals.

A page does not need every interaction to occur in under 200 milliseconds to provide a good overall field result.

The useful objective is to eliminate the interactions that create meaningful delays for users.

Does Reducing JavaScript Always Improve INP?

No.

Reducing unnecessary JavaScript is often helpful, but INP is about the complete interaction-to-next-paint experience.

A page can have relatively little JavaScript and still experience poor responsiveness because of:

  • Expensive layout
  • Large DOM updates
  • Rendering work
  • Main-thread contention
  • Third-party scripts

Likewise, a page with substantial JavaScript can remain responsive if that work is well scheduled and does not interfere with user interactions.

The question is not:

“How much JavaScript does the page have?”

It is:

“How much work does the browser have to perform when the user interacts?”

INP Optimization Checklist

JavaScript

  • Identify expensive scripts
  • Remove unused JavaScript
  • Reduce unnecessary execution
  • Split large bundles where appropriate
  • Delay non-critical code
  • Review framework rendering

Event handlers

  • Identify slow handlers
  • Keep immediate interaction work small
  • Avoid unnecessary calculations
  • Avoid unnecessary DOM updates
  • Use debouncing where appropriate
  • Use throttling where appropriate
  • Consider event delegation for suitable interfaces

Long tasks

  • Find tasks longer than 50 ms
  • Identify what creates them
  • Break up expensive work where appropriate
  • Yield to the browser between chunks
  • Move suitable computation to Web Workers

DOM and rendering

  • Reduce unnecessary DOM changes
  • Avoid layout thrashing
  • Batch DOM reads and writes
  • Avoid rendering unnecessary content
  • Review expensive style and layout work

Third parties

  • Audit external scripts
  • Remove unnecessary services
  • Delay non-critical third-party code
  • Load functionality only where needed

Testing

  • Check field data
  • Identify problematic interactions
  • Record interactions in DevTools
  • Compare before and after
  • Validate real-user performance

Final Verdict

Improving INP is fundamentally about giving the browser room to respond.

JavaScript is frequently part of the problem, but the deeper issue is usually excessive main-thread work.

An event handler may perform too many calculations. A long task may occupy the browser when a user clicks. A large DOM update may trigger expensive layout and rendering. A third-party script may compete for CPU time at exactly the wrong moment.

The most effective approach is therefore to diagnose the interaction itself.

Find the slow interaction.

Find what occupies the main thread.

Find the work that does not need to happen immediately.

Then remove it, reduce it, split it, delay it, or move suitable computation away from the main thread.

Fast INP is not about making JavaScript disappear. It is about making the browser responsive when users need it most.

Share your question | suggestion

Building a new free website tool, plugin, App, etc all ideas are most welcomed !

Leave a Reply

Your email address will not be published. Required fields are marked *

Frequently Asked Questions

Answers to common questions about Core Web Vitals, PageSpeed Insights and field vs lab data.

What is the biggest cause of poor INP?

There is no single cause. Excessive JavaScript execution, long main-thread tasks, expensive event handlers, DOM updates, layout work, rendering, and third-party scripts can all contribute.

What is a long task?

A long task is a main-thread task that runs for more than 50 milliseconds. Long tasks can prevent the browser from responding promptly to user input.

Does reducing JavaScript file size improve INP?

It can help, particularly if less code needs to be downloaded, parsed, and executed. But execution cost and interaction behavior matter more than transfer size alone.

Can CSS cause poor INP?

Yes. Interactions that trigger expensive style recalculation, layout, or rendering can contribute to interaction delay even when JavaScript itself is not particularly slow.

How do I know which interaction is hurting INP?

Field diagnostics can sometimes identify the interaction and element involved. You can then reproduce that interaction in Chrome DevTools and inspect the performance trace.

Does JavaScript directly determine INP?

JavaScript is a common contributor, but INP measures the overall delay from an interaction until the next visual update. Browser rendering and other main-thread work also matter.

Will async and defer improve INP?

They can improve loading behavior and reduce parser blocking, but they do not automatically make JavaScript execution cheaper. A script that executes later can still consume substantial main-thread time.

Should I move JavaScript to a Web Worker?

Only suitable work should be moved. Web Workers are useful for computational tasks that do not need direct DOM access, but they add communication and architectural complexity.

Does a large DOM cause poor INP?

A large DOM does not automatically produce poor INP. Problems arise when interactions cause expensive operations across that DOM.

Is 200 ms the maximum acceptable interaction time?

No. The 200 ms threshold is the boundary for a “good” INP result. It is a performance target, not a rule saying every interaction above 200 ms is unacceptable.

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    Let's connect to chat