Core Web Vitals 2026: INP & LCP Optimization Guide
Bottom Line
Treat LCP as a discovery and delivery problem, and treat INP as a main-thread and rendering problem. Field data at the 75th percentile should decide where you spend engineering time.
Key Takeaways
- ›Good INP is 200 ms or less; poor starts above 500 ms.
- ›Good LCP is 2.5 s or less; poor starts above 4.0 s.
- ›Measure with CrUX/RUM first, then reproduce slow paths in DevTools and Lighthouse.
- ›Never lazy-load a likely LCP image; prefer early discovery plus fetchpriority="high".
- ›Most bad INP comes from long tasks, layout thrashing, large DOM work, or delayed next-frame rendering.
As of April 27, 2026, the winning pattern for Core Web Vitals is straightforward: optimize LCP by getting the right resource discovered and rendered earlier, and optimize INP by keeping the main thread free for interaction work. This reference guide is built for fast scanning, not deep theory, so you can move from metric to root cause to fix without digging through five separate docs.
Metrics and Benchmarks
The official thresholds have not changed: INP measures responsiveness, LCP measures perceived load speed, and both should be evaluated at the 75th percentile across mobile and desktop. The definitions and thresholds below align with current guidance from web.dev on INP, web.dev on LCP, and Core Web Vitals thresholds.
Bottom Line
If your LCP is slow, start with discovery, priority, and TTFB. If your INP is slow, start with long tasks, event callback cost, layout work, and delayed next-frame rendering.
2026 Threshold Table
| Metric | Good | Needs Improvement | Poor | What It Tells You |
|---|---|---|---|---|
| INP | ≤ 200 ms | > 200 ms and ≤ 500 ms | > 500 ms | How quickly the page responds to clicks, taps, and key presses. |
| LCP | ≤ 2.5 s | > 2.5 s and ≤ 4.0 s | > 4.0 s | When the main content likely becomes visible in the viewport. |
How To Read The Numbers
- Use field data to decide whether the problem is real for users.
- Segment by mobile and desktop because percentile behavior often differs sharply.
- Prefer URL-level data when available; fall back to origin-level data carefully.
- Expect lab tools to explain causes, not to replace production telemetry.
Measurement Workflow
A reliable workflow is field first, then lab reproduction, then targeted fixes. Chrome guidance consistently favors CrUX or your own RUM for prioritization, with DevTools and Lighthouse used to isolate root causes.
Field First
- Check PageSpeed Insights for CrUX data before trusting a one-off local run.
- Use your own RUM if you need interaction context, affected elements, or release-by-release attribution.
- Compare mobile URL, desktop URL, mobile origin, and desktop origin views before assigning work.
- Use TTFB and FCP as supporting diagnostics for slow LCP.
Minimal Production Instrumentation
import {onINP, onLCP} from 'web-vitals/attribution';
function sendToAnalytics(metric) {
navigator.sendBeacon('/vitals', JSON.stringify({
name: metric.name,
id: metric.id,
value: metric.value,
rating: metric.rating,
attribution: metric.attribution
}));
}
onINP(sendToAnalytics);
onLCP(sendToAnalytics);
This pattern follows the official web-vitals package shape and is the fastest path to production evidence. If you want to clean up snippets before pasting them into docs or incident reports, TechBytes' Code Formatter is a convenient handoff step.
Lab Reproduction
- Record a trace in the Chrome DevTools Performance panel.
- Use the Insights view to connect failures to specific loading or interaction work.
- Reproduce slow interactions during page load as well as after hydration completes.
- For INP, identify whether the time is going into input delay, processing duration, or presentation delay.
LCP Playbook
LCP rarely improves from one micro-fix. The official optimization model breaks total LCP into TTFB, resource load delay, resource load duration, and element render delay, which is the right mental model for debugging.
LCP Subparts To Watch
| Subpart | Target Share | What Usually Goes Wrong |
|---|---|---|
| TTFB | ~40% | Slow document delivery, redirects, cache misses, origin latency. |
| Resource Load Delay | < 10% | The browser discovers the LCP resource too late. |
| Resource Load Duration | ~40% | Large images, cross-origin connection setup, weak compression. |
| Element Render Delay | < 10% | Render-blocking CSS or JS, late font availability, hidden hero reveal. |
Highest-Value LCP Fixes
- Make the likely LCP resource discoverable in the initial HTML.
- Preload a CSS background hero image or required web font if it gates the final paint.
- Never use loading="lazy" on a likely LCP image.
- Use fetchpriority="high" on the hero <img> when it is likely the final LCP element.
- Keep critical resources on the same origin when possible to avoid extra connection setup.
Reference Markup
<link rel="preload" as="image" href="/images/hero.webp" fetchpriority="high" type="image/webp">
<img
src="/images/hero.webp"
width="1600"
height="900"
fetchpriority="high"
alt="Product hero"
>
Common LCP Anti-Patterns
- Hero content injected by JavaScript after the document is already parsed.
- Background-image heroes with no preload hint.
- Carousel images competing with the real hero for bandwidth.
- Too many resources marked with fetchpriority="high".
INP Playbook
INP is the practical measure of whether the interface stays responsive after load. The official breakdown is simple: reduce input delay, shorten processing duration, and get the next frame on screen sooner.
Map The Delay Before You Fix It
- Input delay: time before the interaction callback starts.
- Processing duration: callback execution time.
- Presentation delay: time until the browser paints visual feedback.
- Remember that slow interactions inside iframes still count toward page-level INP.
Most Reliable INP Fixes
- Break up long tasks so interactions do not wait behind unrelated work.
- Run only visual-update logic before the next frame; defer non-critical work.
- Avoid layout thrashing from writing styles and then reading layout in the same task.
- Reduce large DOM costs when interactions trigger broad re-rendering.
- Use content-visibility for off-screen regions when it meaningfully cuts rendering work.
Yield Non-Critical Work
textBox.addEventListener('input', (inputEvent) => {
updateTextBox(inputEvent);
requestAnimationFrame(() => {
setTimeout(() => {
const text = textBox.textContent;
updateWordCount(text);
checkSpelling(text);
saveChanges(text);
}, 0);
});
});
This pattern mirrors current web.dev guidance for INP optimization: keep the current interaction light, let the browser paint, then push secondary work into a later task.
Common INP Smells
- Recurring timers that keep the main thread busy during likely interaction windows.
- Large client-side HTML rendering after click or input.
- Animation work that competes with input on the main thread.
- Very large DOM trees that make each update expensive.
Reference Cheat Sheet
This section is designed for scan speed. Use the live filter to narrow the command and config list by metric, tool, or action.
Commands: Audit Runs
npm install -g lighthouse
lighthouse https://example.com/
lighthouse https://example.com/ --view
lighthouse https://example.com/ --preset=desktop
- Lighthouse currently requires Node 22 or later.
- Use --view when you want the HTML report to open automatically.
- Use --preset=desktop when the desktop experience is the real priority.
Commands: Artifacts and Re-Runs
lighthouse https://example.com/ --output=json --output-path=./report.json --save-assets
lighthouse https://example.com/ -GA=./latest-run
lighthouse https://example.com/ -A=./latest-run
- Use --save-assets when you need the trace and DevTools log for deeper analysis.
- Use -GA to gather and audit while also saving artifacts.
- Use -A to audit previously saved artifacts without a fresh browser run.
Configuration: LCP
<link rel="preload" as="image" href="/images/hero.webp" fetchpriority="high" type="image/webp">
<img src="/images/hero.webp" fetchpriority="high" alt="Hero">
- Use preload when the LCP image is hidden behind CSS or JS discovery.
- Use fetchpriority="high" for the real hero, not for every above-the-fold asset.
- Do not use loading="lazy" on a likely LCP image.
Configuration: INP
.feed-section {
content-visibility: auto;
}
button.addEventListener('click', () => {
renderCriticalState();
requestAnimationFrame(() => {
setTimeout(runSecondaryWork, 0);
});
});
- Use content-visibility: auto to keep off-screen rendering work from dominating interaction costs.
- Keep pre-paint logic minimal, then defer analytics, indexing, and secondary UI work.
- Profile layout reads and writes together when DevTools shows repeated Layout or Recalculate Style.
Keyboard Shortcuts: Chrome DevTools
| Action | Mac | Windows / Linux |
|---|---|---|
| Open DevTools | Command + Option + I |
F12 or Control + Shift + I |
| Open Command Menu | Command + Shift + P |
Control + Shift + P |
| Start / stop Performance recording | Command + E |
Control + E |
| Save Performance recording | Command + S |
Control + S |
| Search in current panel | Command + F |
Control + F |
| Toggle Drawer | Escape |
Escape |
| Hard reload | Command + Shift + R |
Control + Shift + R |
Full shortcut coverage is documented in the official Chrome DevTools keyboard shortcuts reference.
Advanced Usage
- Use the attribution build of web-vitals when you need actionable field clues, not just scores.
- Overlay field context with local traces in the DevTools Performance panel to match production pain with lab evidence.
- For LCP, compare document timing and the LCP resource waterfall before touching image compression settings.
- For INP, verify whether the slow interaction happens during startup, after hydration, or inside an iframe.
Ship Checklist
Use this as the final pass before calling the work done.
- Verify CrUX or RUM shows the page actually has an INP or LCP problem.
- Confirm the likely LCP element and when its resource starts loading.
- Check that no likely hero image is using loading="lazy".
- Record one slow interaction and separate input delay, callback time, and presentation delay.
- Re-test on mobile and desktop after each meaningful fix.
- Keep one production dashboard for release-by-release regression detection.
Frequently Asked Questions
What is a good INP score in 2026? +
Why does Lighthouse show a better LCP than CrUX or RUM? +
Should I lazy-load the hero image if it is the LCP element? +
loading="lazy" because it adds unnecessary resource load delay. Prefer early HTML discovery, rel="preload" when needed, and fetchpriority="high" for the real hero.What usually causes poor INP on modern front ends? +
Get Engineering Deep-Dives in Your Inbox
Weekly breakdowns of architecture, security, and developer tooling — no fluff.
Related Deep-Dives
Go 1.26 Profiling: Optimize High-Throughput Microservices
A practical profiling workflow for finding latency bottlenecks and validating performance fixes.
System Architecture[Deep Dive] C++ Games in Browser: WASI 2.0 & WebGPU Guide
A browser-focused performance and architecture guide for teams pushing interactive workloads to the web.
System Architecture[Deep Dive] The WebAssembly Component Model: 2026 Architecture
A systems-level look at modular browser-adjacent runtime design and performance tradeoffs.