Improve LCP, CLS, and FID
# Core Web Vitals Optimization
You are an expert in optimizing Core Web Vitals (LCP, FID/INP, CLS) for better user experience and SEO rankings.
## Key Principles
- Optimize LCP with priority hints and preloading
- Reduce CLS with explicit size attributes
- Improve INP with code splitting and deferral
- Monitor with Real User Monitoring (RUM)
- Set and enforce performance budgets
## Largest Contentful Paint (LCP) Optimization
```tsx
// Optimize hero image loading
import Image from "next/image";
export function HeroSection() {
return (
<section className="hero">
{/* Priority loading for LCP element */}
<Image
src="/hero-image.webp"
alt="Hero"
width={1200}
height={600}
priority // Preload this image
sizes="100vw"
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j..."
/>
<h1>Welcome to Our Site</h1>
</section>
);
}
// Preload critical resources in head
// app/layout.tsx
export default function RootLayout({ children }) {
return (
<html>
<head>
{/* Preload LCP image */}
<link
rel="preload"
as="image"
href="/hero-image.webp"
fetchPriority="high"
/>
{/* Preconnect to critical origins */}
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://cdn.example.com" crossOrigin="" />
{/* Preload critical font */}
<link
rel="preload"
as="font"
type="font/woff2"
href="/fonts/inter-var.woff2"
crossOrigin=""
/>
{/* Inline critical CSS */}
<style dangerouslySetInnerHTML={{
__html: `
.hero { min-height: 60vh; background: #f5f5f5; }
h1 { font-size: 2.5rem; font-weight: 700; }
`
}} />
</head>
<body>{children}</body>
</html>
);
}
```
## Cumulative Layout Shift (CLS) Prevention
```tsx
// Always specify dimensions for media
function ProductCard({ product }) {
return (
<article className="product-card">
{/* Explicit width and height prevent layout shift */}
<img
src={product.image}
alt={product.name}
width={300}
height={300}
loading="lazy"
decoding="async"
/>
{/* Reserve space for dynamic content */}
<div className="product-info" style={{ minHeight: "120px" }}>
<h2>{product.name}</h2>
<p>{product.description}</p>
</div>
</article>
);
}
// CSS for preventing layout shifts
const styles = `
/* Aspect ratio boxes for responsive images */
.image-container {
aspect-ratio: 16 / 9;
overflow: hidden;
}
.image-container img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Reserve space for ads */
.ad-slot {
min-height: 250px;
background: #f0f0f0;
}
/* Prevent font swap shift */
@font-face {
font-family: 'Inter';
font-display: optional; /* or swap with size-adjust */
src: url('/fonts/inter.woff2') format('woff2');
size-adjust: 100%;
ascent-override: 90%;
descent-override: 20%;
}
/* Skeleton loaders with exact dimensions */
.skeleton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
`;
```
## Interaction to Next Paint (INP) Optimization
```tsx
// Defer non-critical JavaScript
import dynamic from "next/dynamic";
// Lazy load heavy components
const HeavyChart = dynamic(() => import("./HeavyChart"), {
loading: () => <div className="skeleton chart-skeleton" />,
ssr: false,
});
// Use Web Workers for heavy computation
function useWorker() {
const workerRef = useRef<Worker>();
useEffect(() => {
workerRef.current = new Worker(
new URL("../workers/heavy-task.worker.ts", import.meta.url)
);
return () => workerRef.current?.terminate();
}, []);
const processData = useCallback((data: any) => {
return new Promise((resolve) => {
workerRef.current?.postMessage(data);
workerRef.current?.onmessage = (e) => resolve(e.data);
});
}, []);
return { processData };
}
// Debounce expensive event handlers
function SearchInput() {
const [query, setQuery] = useState("");
const debouncedSearch = useMemo(
() => debounce((q: string) => {
// Expensive search operation
performSearch(q);
}, 300),
[]
);
return (
<input
type="search"
value={query}
onChange={(e) => {
setQuery(e.target.value);
debouncedSearch(e.target.value);
}}
/>
);
}
// Use CSS containment for complex layouts
const containmentStyles = `
.card-grid {
contain: layout style paint;
}
.card {
contain: content;
content-visibility: auto;
contain-intrinsic-size: 300px 400px;
}
`;
```
## Real User Monitoring (RUM)
```tsx
// lib/web-vitals.ts
import { onCLS, onFID, onLCP, onINP, onTTFB, onFCP } from "web-vitals";
type Metric = {
name: string;
value: number;
rating: "good" | "needs-improvement" | "poor";
navigationType: string;
};
function sendToAnalytics(metric: Metric) {
// Send to your analytics endpoint
fetch("/api/analytics/vitals", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
...metric,
url: window.location.href,
timestamp: Date.now(),
connection: (navigator as any).connection?.effectiveType,
deviceMemory: (navigator as any).deviceMemory,
}),
// Use sendBeacon for reliability
keepalive: true,
});
// Also send to Google Analytics
if (window.gtag) {
window.gtag("event", metric.name, {
value: Math.round(metric.value),
metric_rating: metric.rating,
non_interaction: true,
});
}
}
export function initWebVitals() {
onCLS(sendToAnalytics);
onFID(sendToAnalytics);
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onTTFB(sendToAnalytics);
onFCP(sendToAnalytics);
}
// Usage in _app.tsx or layout.tsx
useEffect(() => {
initWebVitals();
}, []);
```
## Performance Budget Configuration
```json
// .lighthouserc.json
{
"ci": {
"assert": {
"assertions": {
"categories:performance": ["error", { "minScore": 0.9 }],
"largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
"cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }],
"total-blocking-time": ["error", { "maxNumericValue": 200 }],
"first-contentful-paint": ["warn", { "maxNumericValue": 1800 }],
"speed-index": ["warn", { "maxNumericValue": 3000 }]
}
}
}
}
```
## Best Practices
- Prioritize above-the-fold content loading
- Use loading="lazy" for below-fold images
- Reserve space for dynamic content
- Defer third-party scripts
- Use efficient CSS selectors
- Monitor metrics in production with RUMThis Performance prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their performance implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For Performance projects, consider mentioning your framework version, coding style, and any specific libraries you're using.