Skip to content
intermediatePhase 38 · Web Performance

Largest Contentful Paint

Optimize LCP by improving server response, resource loading, and rendering.

30m
0 problems
Topic Progress0%

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

  1. Slow server response time
  2. Render-blocking resources
  3. Slow resource load times
  4. Client-side rendering

Debugging LCP

  1. Open Chrome DevTools → Performance panel
  2. Record a page load
  3. Look for the LCP marker in the timeline
  4. Identify the LCP element in the Elements panel
  5. 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

0/3solved
Build Largest Contentful Paint Component

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 needed
Largest Contentful Paint Testing

Write 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 tests
Largest Contentful Paint Performance

Optimize 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 analysis

Quiz

1. What is a good LCP score?

Question 1 options

2. Which element types are considered for LCP?

Question 2 options

3. What does fetchPriority="high" do?

Question 3 options

4. Why preload critical resources?

Question 4 options

5. What is render-blocking CSS?

Question 5 options

Flashcards

Question

What is LCP?

Answer

Largest Contentful Paint - measures when the largest content element becomes visible.

Question

What is a good LCP threshold?

Answer

2.5 seconds or less for a good rating.

Question

What is fetchPriority?

Answer

A browser hint that prioritizes loading of specific resources.

Question

What is preload?

Answer

A resource hint that tells the browser to start downloading a resource immediately.

Question

What is Largest Contentful Paint?

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

  1. Optimize images (WebP, srcset)
  2. Preload critical resources
  3. Remove render-blocking resources
  4. Improve server response time
  5. Use fetchPriority="high" for LCP element

Tools

  • Chrome DevTools Performance panel
  • web-vitals library
  • Lighthouse