How to Improve Your Webpage Speed for Faster Website
Updated: March 27, 2026
TL;DR
Focus on Core Web Vitals: LCP (Largest Contentful Paint under 2.5s), INP (Interaction to Next Paint under 200ms), and CLS (Cumulative Layout Shift under 0.1). Use AVIF images, Speculation Rules API for instant navigation, HTTP/3, and Lighthouse to measure. Speed directly impacts SEO rankings and conversion rates.
Page speed is not a nice-to-have. Google's ranking algorithm rewards fast sites. Users abandon slow sites (50% bounce rate on pages over 3 seconds). And for your business, every 100ms improvement in load time can increase conversions by 1-7%.
In 2026, optimizing speed is table stakes. But the toolkit has evolved. The focus has shifted from raw load time to interaction responsiveness—how quickly users can actually do something on your page. This guide covers the metrics that matter and the practical techniques to improve them.
Understanding Core Web Vitals
Core Web Vitals are three metrics Google uses for ranking. They measure real user experience:
Largest Contentful Paint (LCP)
LCP measures how quickly the main content appears. Specifically, the largest visible element on screen.
Target: Under 2.5 seconds
0s ─────────────────────── 4s
├─── Good (LCP <2.5s)
├─── Fair (2.5s-4s)
├─── Poor (>4s)
What counts as "contentful"?
- Images
- Heading and body text
- Video poster images
- Elements with background images
What doesn't count?
- SVG elements
- Canvas elements
- Iframe content
How to improve LCP:
- Lazy load below-the-fold images:
<img src="hero.avif" loading="lazy" alt="Hero image" />
- Optimize the critical path: Minimize CSS and JavaScript that blocks rendering.
// Before: render-blocking CSS
<link rel="stylesheet" href="styles.css" />
// After: critical CSS inline, defer the rest
<style>{criticalCSS}</style>
<link rel="stylesheet" href="styles.css" media="print" onload="this.media='all'" />
- Preload the LCP element:
<link rel="preload" as="image" href="hero.avif" />
Interaction to Next Paint (INP)
INP measures how responsive your site is to user interactions. When a user clicks, scrolls, or types, how long until the next paint? This replaced First Input Delay (FID) in March 2024.
Target: Under 200 milliseconds
Why does this matter? A sluggish response makes your site feel broken, even if it eventually loads.
0ms ──────────────────── 500ms
├─── Good (INP <200ms)
├─── Fair (200-500ms)
├─── Poor (>500ms)
How to improve INP:
- Break up long JavaScript tasks (longer than 50ms becomes noticeable):
// Bad: blocks for 100ms
function processLargeDataset(data) {
const result = data
.map(item => expensiveCalculation(item))
.filter(item => item.isValid);
updateUI(result);
}
// Good: break into chunks
async function processLargeDataset(data) {
const chunkSize = 100;
for (let i = 0; i < data.length; i += chunkSize) {
const chunk = data.slice(i, i + chunkSize);
const result = chunk
.map(item => expensiveCalculation(item))
.filter(item => item.isValid);
updateUI(result);
// Yield to browser to handle other tasks
await new Promise(resolve => setTimeout(resolve, 0));
}
}
- Use web workers for expensive computations:
// main.js
const worker = new Worker('worker.js');
worker.postMessage({ data: largeDataset });
worker.onmessage = (event) => updateUI(event.data);
// worker.js
self.onmessage = (event) => {
const result = complexCalculation(event.data);
self.postMessage(result);
};
- Defer non-critical JavaScript:
<!-- Critical for interactivity -->
<script src="interactive.js"></script>
<!-- Deferred: analytics, non-essential features -->
<script defer src="analytics.js"></script>
Cumulative Layout Shift (CLS)
CLS measures unexpected layout changes. When content suddenly moves while users are trying to interact, it's a poor experience.
Target: Under 0.1
Example: You're about to click a button, but an ad loads and pushes the button down. You accidentally click the ad instead. That's layout shift.
How to improve CLS:
- Reserve space for dynamic content:
<!-- Bad: ad can cause shift -->
<div id="ad"></div>
<!-- Good: reserve space -->
<div style="width: 300px; height: 250px;">
<div id="ad"></div>
</div>
- Use
content-visibilityto prevent shifting:
/* Prevent cumulative layout shift on images */
img {
content-visibility: auto;
}
- Avoid inserting content above existing content:
// Bad: prepend new items (shifts everything down)
setItems([...newItems, ...items]);
// Good: append new items (no shift)
setItems([...items, ...newItems]);
Image Optimization
Images are typically 50-80% of page weight. Optimizing them has the biggest impact.
AVIF: Next-Gen Format
AVIF is smaller than WebP, which is smaller than JPEG. In 2026, AVIF support is widespread (all modern browsers).
<picture>
<source srcset="image.avif" type="image/avif" />
<source srcset="image.webp" type="image/webp" />
<img src="image.jpg" alt="Description" />
</picture>
Typical file sizes for the same image:
- JPEG: 100KB
- WebP: 60KB
- AVIF: 40KB
Use ImageOptim, TinyPNG, or Squoosh to compress.
Responsive Images
Serve different sizes based on device width:
<img
src="image-400w.avif"
srcset="
image-400w.avif 400w,
image-800w.avif 800w,
image-1200w.avif 1200w
"
sizes="(max-width: 600px) 90vw, (max-width: 1200px) 70vw, 1200px"
alt="Product image"
/>
This tells the browser:
- On screens 600px or smaller, load an image 90% of viewport width
- On screens 600-1200px, load 70% of viewport width
- Larger screens, load a fixed 1200px image
Network Optimization
Speculation Rules API
Speculation Rules let the browser prefetch or prerender pages the user is likely to visit next.
<script type="speculationrules">
{
"prerender": [
{
"source": "list",
"urls": ["/checkout", "/confirmation"]
}
]
}
</script>
This way, if a user clicks "Proceed to Checkout," the page is already loaded in a hidden tab.
HTTP/3 and Early Hints
HTTP/3 is faster than HTTP/2. If your hosting supports it, enable it.
HTTP 103 Early Hints tells the browser to start fetching critical resources before the main HTML is ready:
HTTP/1.1 103 Early Hints
Link: </css/styles.css>; rel=preload; as=style
Link: </js/app.js>; rel=preload; as=script
HTTP/1.1 200 OK
<!-- HTML content -->
Most CDNs (Cloudflare, Fastly) support this. Check your hosting.
Measuring with Lighthouse
Lighthouse is the industry standard for measuring performance.
# Using Lighthouse CLI
npm install -g @google/lighthouse
lighthouse https://example.com --view
Or use Chrome DevTools: F12 → Lighthouse tab → "Analyze page load".
What to look for:
- Opportunities: Ranked by potential impact (e.g., "Eliminate render-blocking resources: 2.4s savings")
- Diagnostics: Details on what's slow
- Passed audits: What's working well
Set a target score for each category:
- Performance: 90+
- Accessibility: 95+
- Best Practices: 95+
- SEO: 100
Real User Monitoring (RUM)
Lab tools like Lighthouse test your site in a controlled environment. Real User Monitoring (RUM) measures actual user experience.
Web Vitals Library
import {
getCLS,
getFID,
getFCP,
getLCP,
getTTFB,
} from 'web-vitals';
getCLS(console.log); // Cumulative Layout Shift
getFCP(console.log); // First Contentful Paint
getLCP(console.log); // Largest Contentful Paint
getTTFB(console.log); // Time to First Byte
// Send to analytics
getLCP((metric) => {
analytics.track('Core Web Vitals', {
metric: metric.name,
value: metric.value,
rating: metric.rating, // 'good', 'needs-improvement', 'poor'
});
});
Services like Vercel Analytics, Google Analytics 4, or Datadog show Core Web Vitals from real users.
Performance Budget
Set targets for specific resources:
// Budget in lighthouse config
{
"budgets": [
{
"type": "bundle",
"name": "main",
"baseline": 150000,
"maxSize": 170000
},
{
"type": "font",
"name": "Inter",
"maxSize": 50000
}
]
}
Run Lighthouse CI in your CI/CD to fail builds that exceed the budget.
Common Pitfalls
Too many third-party scripts: Analytics, ads, chat widgets—each adds overhead. Load them asynchronously.
Unoptimized web fonts: System fonts load instantly. Web fonts cause a flash of invisible text (FOIT). Use font-display strategies:
@font-face {
font-family: 'Inter';
src: url('inter.woff2') format('woff2');
font-display: swap; /* Show fallback until font loads */
}
Large bundles: Tree-shake unused code, code-split by route, lazy-load components:
// Before: entire library bundled
import { datePicker, dropdown, modal } from 'ui-lib';
// After: lazy load what you need
const datePicker = lazy(() => import('ui-lib/DatePicker'));
Uncompressed responses: Ensure gzip/brotli compression is enabled on your server.
Key Takeaways
Speed optimization is a continuous process:
- Measure first: Use Lighthouse and Google Analytics to identify bottlenecks
- Focus on Core Web Vitals: LCP, INP, CLS—these directly impact rankings
- Optimize images: AVIF + responsive images yield the biggest gains
- Break up JavaScript: Long tasks kill INP scores
- Measure real users: Lab tools miss real-world conditions
- Monitor continuously: Set performance budgets and enforce them in CI
A 1-second improvement in load time can mean thousands of dollars in additional revenue for e-commerce. Speed is not optional.