{"id":4318,"date":"2024-11-05T10:20:28","date_gmt":"2024-11-05T15:20:28","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=4318"},"modified":"2024-11-05T10:20:29","modified_gmt":"2024-11-05T15:20:29","slug":"mastering-interaction-to-next-paint-inp","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/mastering-interaction-to-next-paint-inp\/","title":{"rendered":"Mastering Interaction to Next Paint (INP)"},"content":{"rendered":"\n<p>The web keeps changing\u2014and so do the ways we measure web performance. Google recently updated its&nbsp;<strong>Core Web Vitals<\/strong>&nbsp;metrics, dropping First Input Delay (FID) in favor of a new and improved interaction metric: Interaction to Next Paint (INP).<\/p>\n\n\n\n<p>FID was a step in the right direction, measuring how quickly a site responds to the first interaction. But it fell short by focusing only on that initial action, leaving out every click and type that follows. It also emphasized blocking time over total processing time, missing the real story behind user experience.<\/p>\n\n\n\n<p>How is INP different? We\u2019ll dive into exactly what it\u2019s measuring, how to diagnose it, and, most importantly, how to fix it so your website interactions feel fast and responsive.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-interaction-to-next-paint-measures\">What \u201cInteraction to Next Paint\u201d Measures<\/h2>\n\n\n\n<p>INP monitors every interaction a user makes with a page\u2014whether it\u2019s a click, tap, or key press. It measures the time it takes for each of these interactions to trigger a visible change, or&nbsp;<strong>\u201cnext paint,\u201d<\/strong>&nbsp;on the screen, capturing every millisecond from receiving the input to updating the display.<\/p>\n\n\n\n<p>Over the lifetime of a page, there should (hopefully) be lots of user interactions. Your INP score is determined by the&nbsp;<strong>\u201cworst\u201d interaction<\/strong>&nbsp;on the page\u2014the one with the longest delay until a response.<\/p>\n\n\n\n<p>It may sound harsh, but it\u2019s realistic. If just one interaction lags, that\u2019s what users remember. By focusing on the most significant delays, INP spotlights the interactions that need the most attention to create a truly responsive experience.<\/p>\n\n\n\n<p>To hit a good INP score, a page needs to respond to every interaction in under 200 milliseconds.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"256\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp_score_ranges.png?resize=1024%2C256&#038;ssl=1\" alt=\"\" class=\"wp-image-4321\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp_score_ranges.png?resize=1024%2C256&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp_score_ranges.png?resize=300%2C75&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp_score_ranges.png?resize=768%2C192&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp_score_ranges.png?w=1152&amp;ssl=1 1152w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"why-inp-matters\">Why INP Matters<\/h2>\n\n\n\n<p>INP directly measures a website\u2019s interactivity\u2014how responsive the site feels to users as they interact. We\u2019ve all had that frustrating experience of clicking a button, only to have nothing happen right away. Suddenly, you\u2019re wondering if the click registered or if you need to try again. That\u2019s the feeling of poor interactivity.<\/p>\n\n\n\n<p>When interactions lag, users feel like the site is \u201cslow,\u201d \u201claggy,\u201d or even \u201cbroken.\u201d It\u2019s a surefire way to frustrate users, lose engagement, and damage credibility.<\/p>\n\n\n\n<p>And if that\u2019s not enough, INP is one of Google\u2019s Core Web Vitals and a factor in SEO rankings. Google doesn\u2019t want to send search traffic to laggy sites, so it penalizes pages that fail their INP scores.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"understanding-inp-measurement-in-detail\">Understanding INP Measurement in Detail<\/h2>\n\n\n\n<p>Before we dive into tactics to fix INP, it\u2019s important to understand how INP is measured. If you\u2019re looking for even more details,&nbsp;<a href=\"https:\/\/requestmetrics.com\/web-performance\/inp-interaction-to-next-paint\/\">check out this deep dive on Interaction to Next Paint<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"interactions\">Interactions<\/h3>\n\n\n\n<p>INP measures the response time for all&nbsp;<strong>discrete interactions<\/strong>\u2014like clicks, taps, drags, and key presses\u2014that users make while on the page. These actions initiate user commands and usually lead to some form of visual feedback, so tracking them is essential for accurately gauging a site\u2019s interactivity.<\/p>\n\n\n\n<p>One common action that&nbsp;<strong>doesn\u2019t<\/strong>&nbsp;factor into INP, however, is&nbsp;<strong>scrolling<\/strong>. Scrolling is typically continuous rather than discrete and has its own performance considerations outside of INP\u2019s scope.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"the-inp-measurement-window\">The INP Measurement Window<\/h3>\n\n\n\n<p>INP measures everything that happens between a user interaction and the next paint event, and a lot can occur in that window. Here\u2019s how it breaks down:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"266\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp_measurement_window.png?resize=1024%2C266&#038;ssl=1\" alt=\"\" class=\"wp-image-4322\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp_measurement_window.png?resize=1024%2C266&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp_measurement_window.png?resize=300%2C78&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp_measurement_window.png?resize=768%2C199&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp_measurement_window.png?resize=1536%2C399&amp;ssl=1 1536w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp_measurement_window.png?w=1564&amp;ssl=1 1564w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Input Delay<\/strong>: When the interaction event is triggered, the browser may already be busy, for instance, executing an obnoxious amount of JavaScript. Since JavaScript can block the main thread, the browser has to wait until it\u2019s finished before it can even start processing the interaction. This waiting period is the&nbsp;<strong>input delay<\/strong>.<\/li>\n\n\n\n<li><strong>Event Handling<\/strong>: Once the main thread is free, the browser can dispatch the event to any associated event handlers\u2014and there could be quite a few. Each event handler needs to be called and completed before moving forward.<\/li>\n\n\n\n<li><strong>Rendering<\/strong>: After all JavaScript is done executing, the browser can calculate what changed in the DOM, update elements and layout, and finally paint the next frame to the viewport.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"inp-and-long-animation-frames-loaf\">INP and Long Animation Frames (LoAF)<\/h3>\n\n\n\n<p>INP is closely related to&nbsp;<strong>Long Animation Frames (LoAF)<\/strong>, as both metrics capture user responsiveness and visual feedback. LoAF measures the time between paint events, regardless of whether an interaction happened, indicating if the browser may have felt \u201cfrozen\u201d to the user.<\/p>\n\n\n\n<p>A slow INP is often accompanied by a Long Animation Frame, which can provide more details on the scripts or activities causing delays. For more information, check out this&nbsp;<a href=\"https:\/\/requestmetrics.com\/web-performance\/long-animation-frame-loaf\/\">detailed guide on Long Animation Frames<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-to-improve-your-inp-score\">How to Improve Your INP Score<\/h2>\n\n\n\n<p>Improving your INP score means reducing the time users wait for visible feedback after they interact. Here are some strategies to make sure your site responds quickly:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Yield to the Main Thread<\/strong>: Avoid monopolizing the main thread with long-running tasks. When you block the main thread, user interactions get stuck waiting. Breaking up heavy tasks with&nbsp;<code>setTimeout<\/code>&nbsp;or&nbsp;<code>requestAnimationFrame<\/code>&nbsp;can reduce delays and keep the main thread open for user input.<\/li>\n\n\n\n<li><strong>Optimize JavaScript<\/strong>: Large JavaScript bundles are often the main culprit for interaction delays. Reduce bundle size through code-splitting, lazy-loading, and minifying to improve response times. Only load what\u2019s necessary at each stage of the user journey.<\/li>\n\n\n\n<li><strong>Reduce Long Animation Frames (LoAF)<\/strong>: A poor INP score often coincides with Long Animation Frames, so addressing LoAF can directly improve INP. This includes avoiding intensive calculations during animations and syncing visuals with the browser\u2019s rendering cycle.<\/li>\n<\/ul>\n\n\n\n<p>Implementing these strategies can bring down your INP score, keeping interactions responsive and making your site feel faster and more polished.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"example-inp-fix\">Example INP Fix<\/h3>\n\n\n\n<p>Let\u2019s have a look at a specific example. Below is a&nbsp;<a href=\"https:\/\/codepen.io\/toddhgardner-the-selector\/pen\/yLmKKVV\">CodePen with a simple form<\/a>&nbsp;that includes a JavaScript event handler triggered each time the user types, changing the class on the button.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_yLmKKVV\" src=\"\/\/codepen.io\/anon\/embed\/yLmKKVV?height=450&amp;theme-id=47434&amp;slug-hash=yLmKKVV&amp;default-tab=js,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed yLmKKVV\" title=\"CodePen Embed yLmKKVV\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>In this example, the JavaScript handler also calls a slow function,&nbsp;<code>renderSearch<\/code>, each time the event fires. Since&nbsp;<code>renderSearch<\/code>&nbsp;is part of the event handler, it slows down the entire animation frame and causes both LoAF and INP issues by blocking the main thread for too long.<\/p>\n\n\n\n<p>Here\u2019s how to fix it:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_bGXvvjp\" src=\"\/\/codepen.io\/anon\/embed\/bGXvvjp?height=450&amp;theme-id=47434&amp;slug-hash=bGXvvjp&amp;default-tab=js,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed bGXvvjp\" title=\"CodePen Embed bGXvvjp\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>In our fix, we wrapped the event handler in&nbsp;<code>requestAnimationFrame<\/code>, which delays execution until just before the next paint. Then, we adjust the button class immediately, while the heavier work in&nbsp;<code>renderSearch<\/code>&nbsp;is delayed with&nbsp;<code>setTimeout<\/code>&nbsp;so it won\u2019t execute until after the paint is complete. This approach prioritizes responsiveness and keeps user feedback snappy by yielding to the main thread.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"wrapping-up\">Wrapping Up<\/h2>\n\n\n\n<p>Interaction to Next Paint (INP) gives us a more complete view of web interactivity by tracking every user interaction throughout a page\u2019s lifecycle. With INP replacing FID as a Core Web Vital, optimizing for it has never been more critical. A strong INP score not only improves user satisfaction by keeping interactions fast and responsive but also boosts your SEO by aligning with Google\u2019s performance standards.<\/p>\n\n\n\n<p>By implementing strategies like yielding to the main thread, optimizing JavaScript, and addressing Long Animation Frames, you can create a smoother, more responsive experience for users. As you tackle these improvements, Real User Monitoring tools like&nbsp;<a href=\"https:\/\/requestmetrics.com\/\">Request Metrics<\/a>&nbsp;can help you track INP and other Core Web Vitals in real-time, showing exactly where delays are occurring and how effective your fixes are.<\/p>\n\n\n\n<p>Making your website interactive and smooth isn\u2019t just about performance scores\u2014it\u2019s about ensuring users have a seamless experience on your site. With INP insights and a focus on responsiveness, you can keep users engaged, happy, and coming back for more.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how Interaction to Next Paint (INP) measures web interactivity, why it matters for user experience and SEO, and practical strategies to keep your site feeling fast and responsive.<\/p>\n","protected":false},"author":33,"featured_media":4326,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[255,70],"class_list":["post-4318","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-inp","tag-performance"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/11\/inp.jpg?fit=1000%2C500&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/4318","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=4318"}],"version-history":[{"count":3,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/4318\/revisions"}],"predecessor-version":[{"id":4325,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/4318\/revisions\/4325"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/4326"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=4318"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=4318"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=4318"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}