Diagnose and Fix LCP and FCP Performance Issues | OpsBlu Docs

Diagnose and Fix LCP and FCP Performance Issues

Debug Largest Contentful Paint and First Contentful Paint failures with specific thresholds, common causes, and proven fixes for images, fonts, and server.

Largest Contentful Paint (LCP) and First Contentful Paint (FCP) measure how quickly users see meaningful content. LCP is a Core Web Vital that directly affects Google rankings. FCP is a diagnostic metric that helps identify what delays the initial render.

Google's Thresholds

Metric Good Needs Improvement Poor
LCP Under 2.5s 2.5s - 4.0s Over 4.0s
FCP Under 1.8s 1.8s - 3.0s Over 3.0s

These thresholds are evaluated at the 75th percentile of real user visits. If your LCP is 2.4s at the median but 3.8s at p75, Google considers it "needs improvement."

What LCP Actually Measures

LCP tracks the render time of the largest visible element in the viewport. This is typically one of four element types:

  • <img> elements (most common -- roughly 70% of pages)
  • <video> elements with a poster image
  • Elements with a CSS background-image
  • Block-level text elements (<h1>, <p>, etc.)

Use Chrome DevTools Performance tab to identify your LCP element. Look for the "LCP" marker in the timings lane, then click it to highlight the element.

Common LCP Failures and Fixes

Slow Server Response (TTFB Over 600ms)

If Time to First Byte exceeds 600ms, LCP cannot possibly score well. Check server-side rendering time, database query performance, and CDN configuration. Target TTFB under 200ms.

Unoptimized Hero Images

The most frequent LCP culprit. Fix with this approach:

<!-- Preload the LCP image so the browser discovers it immediately -->
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high">

<!-- Use responsive images with proper sizing -->
<img
  src="/hero.webp"
  srcset="/hero-400.webp 400w, /hero-800.webp 800w, /hero-1200.webp 1200w"
  sizes="100vw"
  width="1200"
  height="600"
  alt="Descriptive alt text"
  fetchpriority="high"
>

Never lazy-load the LCP image. Set fetchpriority="high" to tell the browser to prioritize it.

Render-Blocking CSS and Fonts

Large CSS files delay FCP because the browser cannot paint until CSSOM is built. Split critical CSS (above-the-fold styles) from non-critical styles. For fonts, use font-display: swap to show text immediately with a fallback font:

@font-face {
  font-family: 'BrandFont';
  src: url('/fonts/brand.woff2') format('woff2');
  font-display: swap;
}

Client-Side Rendering Delays

Single-page applications (React, Vue, Angular) that render content entirely in JavaScript force the browser to download, parse, and execute JS before any content appears. Switch to server-side rendering (SSR) or static generation (SSG) for landing pages and content-heavy pages.

FCP Diagnostic Checklist

FCP fires when the browser renders the first piece of DOM content. If FCP is slow but LCP is acceptable, the issue is usually:

  1. Render-blocking resources -- check the DevTools Network tab for CSS or synchronous JS in the <head> that blocks first paint
  2. Large DOM size -- pages with over 1,500 DOM nodes take longer for the browser to construct the render tree
  3. Web font loading -- invisible text during font loading delays perceived FCP (use font-display: swap or optional)

Measuring in Production

Lab tools (Lighthouse, WebPageTest) show controlled conditions. Field data from CrUX reveals what real users experience. Use both:

  • PageSpeed Insights -- CrUX field data + Lighthouse lab data for any URL
  • Search Console Core Web Vitals -- site-wide field data grouped by URL pattern
  • web-vitals JavaScript library -- send real LCP/FCP measurements to your analytics
import {onLCP, onFCP} from 'web-vitals';

onLCP(metric => sendToAnalytics('LCP', metric.value));
onFCP(metric => sendToAnalytics('FCP', metric.value));