Inp Yield
Inp Yield
• Senior Performance Engineer @ Framer (you might know us from “Framer Motion”)
• I work on Core Web Vitals & other performance related topics
• Participant in W3C WebPerfWG calls, if you have webperf topics, come chat with me
• I like making things fast & accessible for all users of the internet
What’s Interaction-to-Next-Paint (INP)?
https://web.dev/articles/optimize-input-delay
What’s Interaction-to-Next-Paint (INP)?
• A browser tries to render new frames continuously (if needed)
• ‘fast’ is achieved by keeping the main thread free
Key here:
• INP is about giving the browser the opportunity to paint a frame – but doesn’t have
to for great INP*
• Keeping the main thread free makes the UI feel ‘smooth’(er) => improves UX
INP is how fast the browser could paint the next frame after user input
* A browser might skip “Paint” due to optimizations – those count for INP, too
https://web.dev/articles/inp
If your summary now is:
“if you put less work on the main thread,
you improve UX & INP?”
Absolutely.
That’s why INP is a good approximation of felt UX.
Smooth webpages leave a great impression.
An INP eye-opener:
Doing nothing in response to user input allows the browser to paint fast => great INP…
…great INP in that case does not guarantee great UX!
https://www.speedcurve.com/blog/psychology-site-speed/ https://web.dev/articles/rail
https://www.nngroup.com/articles/response-times-3-important-limits/ https://github.com/w3c/event-timing/issues/118#issuecomment-1108700093
<convincing arguments for your boss.slide>
https://developers.google.com/search/docs/appearance/page-experience
Case Studies
Here’s how AI ‘reimagined’ a
real graph I put into ChatGPT:
We shipped big INP improvements in…?
Graph matches the scale of the impact we‘ve seen. Thanks to friends from the RUMvision team, who helped w/ initial triage.
https://www.speedcurve.com/blog/core-web-vitals-inp-mobile/
13% CVR @ 100 ms
vs.
3% CVR @ 250 ms
Ok Jacob. Sold.
What next?
a) Understand how to find your culprits
Guides: web.dev, DebugBear, RUMvision, Speedcurve, Speedkit, NitroPack, …
Field data: Calibre, RUMvision, Treo, WebPerformance Report, RequestMetrics, …
b) Apply fixes
1. Prioritize visible UI work and defer invisible tasks (such as analytics)
2. Yield to the main thread before, or frequently during expensive functions
3. Finish execution faster – improve runtime efficiency, abort previous tasks
and run less JS overall
kurtextrem.de/INP.pdf
Yield Patterns to
keep the UI smooth
Yield Patterns to keep the UI smooth
• Yielding is a way of saying ‘continue this later’
• Simplest way: setTimeout(fn)
Example:
<button onClick={() => {
updateUI()
setTimeout(sendAnalytics)
}}>
setTimeout(() => alert(‘talk done’)
As simple as that.
prompt(“Questions?“)
The end. Follow me on X, @kurtextrem, I (re)tweet webperf stuff
Just kidding. setTimeout is
one way of yielding
(by the way, if you trigger an alert/prompt, it doesn't count as blocking for INP.
Do with that info whatever you feel like doing...)
https://www.debugbear.com/docs/metrics/interaction-to-next-paint#do-alert-and-similar-dialogs-contribute-to-inp
…and a way of breaking up long tasks
https://web.dev/articles/optimize-input-delay
Used since 2007.
https://x.com/jsmarr/status/1801000265811730807
Life of a (browser) frame
Life of a (browser) frame
Based on https://medium.com/@paul_irish/requestanimationframe-scheduling-for-nerds-9c57f7438ef4
Life of a (browser) frame
https://github.com/w3c/long-animation-frames/issues/13#issuecomment-2142366987
Life of a (browser) frame
https://github.com/w3c/long-animation-frames/issues/13#issuecomment-2142366987
How do we ensure it runs after paint?
• INP was about: making sure a browser has the opportunity to paint
• setTimeout alone does not guarantee it
Cons:
• Might not run if a user is about to leave the page
• rAF could be throttled (if tab goes to background)
• setTimeout suffers from ‘queue jumping’ (= might run somewhen)
https://kurtextrem.de/posts/improve-inp
Queue Jumping?
Queue Jumping
• Almost anything running in the browser is a ‘task’ running in a queue
• Tasks can have different priorities
• setTimeout basically puts the callback to the end of the queue
Cons:
• we need to know how long / expensive our tasks are to make sure it
improves INP
• Limited browser support
• ‘continuation’ is slightly more confusing than ‘await paint & run code’
Calling hobby cooks, we now have 2
recipes. What do we do?
yie
ld
To
M
ain
await-interaction-response
yieldToMain in interactionResponse
This is how Framer runs interactionResponse on prod (btw don’t remove the setTimeout fallback)
This us?
Before we continue with more
browser scheduling stuff,
let’s take a look at a practical example.
Cookie Banners
“Accept” (or “Reject”) usually triggers lots of 3rd-party code
UI updates Stuff the user never sees Stuff the user never sees
Before yielding on “Accept”
After yielding: 100ms faster on p75!
Cookie Banners - Fix
• Yield (await paint) before running any CMP accept or reject callbacks
• Also give your CMP vendor a friendly reminder (because they also
might run events you cannot change)
Tips:
• Run it at the (window) `load` event, so that your push function
overrides the GTM function
• Pair it with the yieldUnlessUrgent pattern (rAF + setTimeout) so
you‘re not the one to blame for less visitors ;)
https://www.youtube.com/watch?v=L6gZp3-7w8c
Thank you. Questions?
Contact me on X: @kurtextrem, I (re)tweet webperf stuff
React folks: Check out my previous talk specifically about React & INP, it has a few
more practical examples & useful tips - kurtextrem.de/INP.pdf