What is LCP
What is LCP
Largest Contentful Paint measures when the largest content element becomes visible in the viewport.
LCP Elements
<img>elements<svg>elements inside<svg><video>poster images- Background images loaded via
url() - Block-level elements containing text nodes
Measuring LCP
import { onLCP } from 'web-vitals';
onLCP((metric) => {
console.log('LCP:', metric.value, 'ms');
console.log('Element:', metric.element);
console.log('URL:', metric.url);
console.log('Rating:', metric.rating); // 'good', 'needs-improvement', 'poor'
});
Thresholds
| Rating | Threshold |
|---|---|
| Good | ≤ 2.5 seconds |
| Needs Improvement | ≤ 4.0 seconds |
| Poor | > 4.0 seconds |
Common LCP Issues
- Slow server response time
- Render-blocking resources
- Slow resource load times
- Client-side rendering
Debugging LCP
- Open Chrome DevTools → Performance panel
- Record a page load
- Look for the LCP marker in the timeline
- Identify the LCP element in the Elements panel
- Check Network panel for resource timing
LCP Optimization
LCP Optimization
Image Optimization
// Before: Unoptimized image
<img src="/hero.jpg" />
// After: Optimized image
<img
src="/hero.webp"
srcset="/hero-400.webp 400w, /hero-800.webp 800w, /hero-1200.webp 1200w"
sizes="(max-width: 768px) 100vw, 50vw"
alt="Hero image"
width="1200"
height="600"
fetchPriority="high"
decoding="async"
/>
Preload Critical Resources
<!-- In <head> -->
<link rel="preload" as="image" href="/hero.webp" />
<link rel="preload" as="font" href="/fonts/inter.woff2" type="font/woff2" crossorigin />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="dns-prefetch" href="https://api.example.com" />
Remove Render-Blocking Resources
// Dynamic import for non-critical CSS
const loadNonCriticalCSS = () => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '/non-critical.css';
document.head.appendChild(link);
};
// Load after page is interactive
if ('requestIdleCallback' in window) {
requestIdleCallback(loadNonCriticalCSS);
} else {
setTimeout(loadNonCriticalCSS, 2000);
}
Server-Side Optimization
// Enable compression
const compression = require('compression');
app.use(compression());
// Set proper cache headers
app.use(express.static('public', {
maxAge: '1y',
immutable: true,
}));
// Use HTTP/2
const http2 = require('http2');
const server = http2.createSecureServer({
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
});
Server Response Optimization
Server Response Optimization
Time to First Byte (TTFB)
// Server-side: Reduce TTFB
// 1. Use CDN
// 2. Cache responses
// 3. Optimize database queries
// 4. Use server-side rendering
// Client: Monitor TTFB
import { onTTFB } from 'web-vitals';
onTTFB((metric) => {
console.log('TTFB:', metric.value, 'ms');
});
Resource Hints
// Link hints in HTML
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="dns-prefetch" href="https://api.example.com" />
<link rel="preload" href="/critical.js" as="script" />
// Dynamic hints in JavaScript
const preconnect = (url) => {
const link = document.createElement('link');
link.rel = 'preconnect';
link.href = url;
document.head.appendChild(link);
};
preconnect('https://api.example.com');
Priority Hints
// High priority for LCP element
<img
src="/hero.webp"
fetchPriority="high"
alt="Hero"
/>
// Low priority for below-fold images
<img
src="/thumbnail.webp"
loading="lazy"
fetchPriority="low"
alt="Thumbnail"
/>
Critical CSS
// Inline critical CSS
function Head() {
return (
<head>
<style dangerouslySetInnerHTML={{ __html: criticalCSS }} />
<link rel="preload" href="/styles.css" as="style" />
</head>
);
}
// Extract critical CSS
// npm install critical
const critical = require('critical');
critical.generate({
base: 'dist/',
src: 'index.html',
css: ['dist/styles.css'],
dimensions: [1300, 900],
inline: true,
});
Practice Problems
Create a reusable React component implementing Largest Contentful Paint. Include proper state management and accessibility.
Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where neededWrite unit and integration tests for Largest Contentful Paint using React Testing Library.
Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility testsOptimize Largest Contentful Paint for performance. Consider memoization, code splitting, and bundle size.
Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysisQuiz
1. What is a good LCP score?
2. Which element types are considered for LCP?
3. What does fetchPriority="high" do?
4. Why preload critical resources?
5. What is render-blocking CSS?
Flashcards
Question
What is LCP?
Click to reveal answer
Answer
Largest Contentful Paint - measures when the largest content element becomes visible.
Question
What is a good LCP threshold?
Click to reveal answer
Answer
2.5 seconds or less for a good rating.
Question
What is fetchPriority?
Click to reveal answer
Answer
A browser hint that prioritizes loading of specific resources.
Question
What is preload?
Click to reveal answer
Answer
A resource hint that tells the browser to start downloading a resource immediately.
Question
What is Largest Contentful Paint?
Click to reveal answer
Answer
Largest Contentful Paint is a key concept in frontend development.
Revision Notes
Key Takeaways
- 1.LCP measures loading performance of the largest visible element
- 2.Good LCP is ≤ 2.5 seconds
- 3.Optimize images with modern formats and srcset
- 4.Preload critical resources and remove render-blocking ones
- 5.Use fetchPriority to prioritize LCP elements
Interview Tips
- •Explain what LCP measures and its threshold
- •Discuss strategies for improving LCP
- •Know the difference between preload and preconnect
Cheat Sheet
LCP Cheat Sheet
Threshold
- Good: ≤ 2.5s
- Needs Improvement: ≤ 4.0s
- Poor: > 4.0s
Optimization
- Optimize images (WebP, srcset)
- Preload critical resources
- Remove render-blocking resources
- Improve server response time
- Use fetchPriority="high" for LCP element
Tools
- Chrome DevTools Performance panel
- web-vitals library
- Lighthouse