Web Performance &
Core Web Vitals Optimizer
Interactive guide to diagnosing and fixing Core Web Vitals. Input your metrics to receive targeted optimization strategies and production-ready code snippets.
Core Web Vitals Analyzer
Input your field or lab data to see targeted recommendations
Target: < 2.5s
Target: < 200ms
Target: < 0.1
Based on your metrics, we recommend focusing on: LCP (Largest Contentful Paint), Image Optimization, INP (Interaction to Next Paint).
Prioritize Hero Image Loading
Add fetchpriority="high" to the main hero image to tell the browser to load it as early as possible. Avoid lazy-loading above-the-fold content.
<!-- 2026 Best Practice for Hero Image -->
<img
src="/hero-banner.webp"
alt="Main Hero Banner"
fetchpriority="high"
decoding="sync"
loading="eager"
width="1200"
height="600"
/>Preload Critical Resources
Preload the exact resource needed for LCP (like a late-discovered web font or hero image from CSS) early in the head.
<link
rel="preload"
as="image"
href="/hero-banner.webp"
fetchpriority="high"
/>Implement Server-Side Rendering (SSR)
Ensure the initial HTML sent from the server contains the LCP element completely rendered, reducing client-side rendering delays.
// Next.js (App Router) example
export default async function Page() {
const data = await fetchHeroData();
return (
<main>
<h1>{data.title}</h1>
{/* Avoid loading spinners for LCP element */}
<HeroBanner src={data.imageUrl} />
</main>
);
}Break Up Long Tasks with scheduler.yield()
Use the new scheduler.yield() API to pause long JS tasks, allowing the browser to handle user interactions before resuming work.
async function processLargeArray(items) {
for (let i = 0; i < items.length; i++) {
processItem(items[i]);
// Yield to main thread every 50ms
if (performance.now() % 50 < 5) {
if ('scheduler' in window && 'yield' in scheduler) {
await scheduler.yield();
} else {
// Fallback for older browsers
await new Promise(r => setTimeout(r, 0));
}
}
}
}Debounce Input Handlers
Prevent complex state updates on every keystroke by debouncing or throttling input handlers.
import { useTransition, useState } from 'react';
export function SearchInput() {
const [query, setQuery] = useState('');
const [isPending, startTransition] = useTransition();
const handleChange = (e) => {
// Immediate UI update
const value = e.target.value;
// Defer heavy rendering/fetching
startTransition(() => {
setQuery(value);
});
};
return <input type="text" onChange={handleChange} />;
}Use CSS Containment
Use the 'contain' CSS property to isolate parts of the page, preventing heavy recalcs when DOM changes occur on interaction.
.isolated-widget {
/* Browser won't calculate layout outside this element
when its contents change */
contain: layout style paint;
/* Also consider content-visibility for off-screen items */
content-visibility: auto;
contain-intrinsic-size: 500px;
}Set Explicit Dimensions
Always set explicit width and height attributes on images, videos, and iframes to prevent the layout from shifting when they load.
<img
src="/article-image.jpg"
width="800"
height="450"
alt="Article illustration"
style="width: 100%; height: auto;"
/>Reserve Space with Aspect Ratio
Use the CSS aspect-ratio property to reserve vertical space for responsive elements before they load.
.video-container {
width: 100%;
aspect-ratio: 16 / 9;
background-color: #f3f4f6; /* Placeholder color */
border-radius: 8px;
overflow: hidden;
}
.video-container iframe {
width: 100%;
height: 100%;
}Reserve Space for Dynamic Content
Allocate fixed min-heights for dynamic content containers (like ads, cookie banners, or delayed injects).
/* Reserve space for an ad slot */
.ad-slot-top {
min-height: 250px;
display: flex;
align-items: center;
justify-content: center;
background: #f8f9fa;
}Early Hints (103)
Utilize HTTP 103 Early Hints to tell the browser to start fetching critical resources before the HTML document finishes generating.
// Next.js or Node/Express header configuration
// Headers sent before document generation completes
Link: </styles/main.css>; rel=preload; as=style
Link: </fonts/inter.woff2>; rel=preload; as=font; crossoriginNext-Gen Formats (AVIF)
Serve images in AVIF format for up to 50% better compression than WebP, while falling back to WebP/JPEG for older browsers.
<picture>
<source srcset="/img/photo.avif" type="image/avif" />
<source srcset="/img/photo.webp" type="image/webp" />
<img src="/img/photo.jpg" alt="Description" loading="lazy" width="800" height="600" />
</picture>Responsive Srcset
Provide multiple image resolutions using srcset and sizes so the browser downloads only what it needs.
<img
srcset="img-320w.jpg 320w,
img-800w.jpg 800w,
img-1200w.jpg 1200w"
sizes="(max-width: 600px) 320px,
(max-width: 1000px) 800px,
1200px"
src="img-800w.jpg"
alt="Responsive"
loading="lazy"
/>Font Display Swap & Size-Adjust
Use font-display: swap to ensure text remains visible during font load, and use size-adjust to match fallback font metrics to prevent CLS.
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap;
}
/* Fallback override to match CustomFont metrics */
@font-face {
font-family: 'FallbackOverride';
src: local('Arial');
size-adjust: 98.5%;
ascent-override: 90%;
descent-override: 20%;
}
body {
font-family: 'CustomFont', 'FallbackOverride', sans-serif;
}Variable Fonts
Replace multiple font weights and styles with a single variable font file to drastically reduce total font payload.
@font-face {
font-family: 'Inter';
src: url('/fonts/Inter-Variable.woff2') format('woff2-variations');
font-weight: 100 900;
font-display: swap;
}
h1 { font-weight: 800; }
p { font-weight: 400; }Handpicked Partner Deals & Gear
Discover top-rated mechanical keyboards, 4K monitors, coding software, and curated developer workstation bundles.
Cite & Link This Resource
Backlink MagnetWriting a blog post, GitHub README, or docs? Embed a backlink snippet or badge to cite this cheat sheet.
[Web Performance & Core Web Vitals Optimizer](https://devdossier.com/resources/web-performance-core-vitals) - Interactive Reference & Cheat Sheet via DevDossier