Skip to content
Now accepting Q2 projects — limited slots available. Get started →
SEO · Updated Apr 30, 2026

What is First Contentful Paint (FCP)?

First Contentful Paint (FCP) is a performance metric that measures the time until the browser renders the first piece of DOM content.

What is First Contentful Paint (FCP)?

First Contentful Paint (FCP) is a user-centric performance metric that marks the time from navigation start to when the browser renders the first bit of content from the DOM — text, an image, an SVG, or a non-white <canvas>. It's one of the six metrics tracked in Lighthouse (as of Lighthouse 12) and is reported in Chrome User Experience Report (CrUX) data, which Google uses for ranking signals. Google classifies FCP scores into three buckets: good (≤1.8 seconds), needs improvement (1.8–3.0 seconds), and poor (>3.0 seconds). FCP is distinct from Largest Contentful Paint (LCP), which tracks the largest visible element. A fast FCP matters because it gives users their first visual confirmation that the page is loading. We've found it's the single most impactful metric for perceived speed on content-heavy sites like blogs and landing pages.

How it works

FCP is measured by the browser's Paint Timing API (PerformanceObserver with entryTypes: ['paint']). When the rendering engine completes its first paint that includes DOM content — not just a background color — it fires a first-contentful-paint entry.

Here's how you can observe it in JavaScript:

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.name === 'first-contentful-paint') {
      console.log('FCP:', entry.startTime, 'ms');
      observer.disconnect();
    }
  }
});
observer.observe({ type: 'paint', buffered: true });

The clock starts at navigationStart (or activationStart for prerendered pages) and stops when the browser paints the first content pixel. Several things block FCP:

  • Render-blocking CSS and JS: Any <link rel="stylesheet"> or synchronous <script> in the <head> must be downloaded and parsed before the browser can paint.
  • Slow TTFB: If the server takes 1.2s to respond, your FCP floor is already 1.2s.
  • Large DOM with no visible content above the fold: The parser has to reach paintable content.
  • Web font loading: If text relies on a custom font that hasn't loaded and font-display isn't set to swap or optional, the browser may delay text rendering.

In practice, improving FCP almost always means reducing the critical rendering path: fewer blocking resources, faster server response, and inlined critical CSS.

When to use it

FCP is the right metric to watch when you care about perceived load speed — how quickly a user sees something on screen.

Track FCP when:

  • You're optimizing landing pages where bounce rate correlates with initial render speed
  • You're diagnosing whether the bottleneck is server-side (TTFB) or client-side (render-blocking resources)
  • You need a CrUX-reported metric that feeds into Google's page experience signals
  • You're running A/B tests on critical CSS or font-loading strategies

FCP is less useful when:

  • Your concern is interactivity — use Interaction to Next Paint (INP) instead
  • You want to measure the main content's load time — LCP is more relevant
  • You're building a single-page app where the shell renders instantly but meaningful content loads later (FCP will look great while the user stares at a spinner)

We default to tracking FCP alongside LCP and TTFB on every project. The three together tell you where time is being spent.

FCP vs alternatives

Metric What it measures Good threshold Best for
FCP First DOM content painted ≤1.8s Perceived speed, first feedback
LCP Largest visible element painted ≤2.5s Main content load
TTFB Time to first byte from server ≤800ms Server/network performance
FP (First Paint) Any pixel change (incl. background) N/A (not in CWV) Rarely useful alone
INP Interaction responsiveness ≤200ms Interactivity after load

FCP and LCP are the pair you need. FCP tells you when the page stops feeling blank. LCP tells you when it feels loaded. A big gap between FCP and LCP usually means your hero image or main text block is loading late — often a lazy-loading misconfiguration or a slow API call hydrating the main content.

Real-world example

On a recent Next.js 15 project (App Router, deployed on Vercel), our initial FCP was 2.4s on mobile 4G according to CrUX. We diagnosed the problem in three steps:

  1. TTFB was 650ms — acceptable, not the bottleneck.
  2. Two render-blocking CSS files totaling 89KB were in the <head>. We inlined critical CSS (~4KB) and deferred the rest with media="print" + onload swap.
  3. A Google Font request was adding ~300ms. We switched to next/font with font-display: swap and self-hosted the subset.

Result: FCP dropped to 1.1s on the same connection profile. LCP followed, dropping from 3.1s to 2.0s. Bounce rate on the landing page decreased 14% over the following 30 days. We've repeated this pattern on 50+ projects — the fix is almost always render-blocking resources and fonts.

Frequently asked questions about First Contentful Paint (FCP)

Is FCP the same as LCP?
No. FCP (First Contentful Paint) measures when the browser renders the *first* piece of DOM content — even a small line of text. LCP (Largest Contentful Paint) measures when the *largest* visible element in the viewport finishes rendering, typically a hero image or heading. FCP always fires before or at the same time as LCP. You can have a fast FCP (user sees nav text at 0.9s) but a slow LCP (hero image loads at 3.5s). Both are reported in CrUX and used by Google, but LCP is the one included in Core Web Vitals. FCP is still a Lighthouse audit metric with real ranking influence.
When did FCP become a standard web performance metric?
FCP was introduced as a Lighthouse audit metric in Lighthouse 1.0, which launched in 2017. The underlying Paint Timing API (Level 1) became a W3C Candidate Recommendation, and Chrome began collecting FCP data in the Chrome User Experience Report (CrUX) around the same time. Google formally incorporated page experience signals — including FCP data from CrUX — into search ranking in June 2021 as part of the Core Web Vitals rollout. While FCP itself isn't one of the three Core Web Vitals (those are LCP, INP, and CLS as of 2024), it's still prominently featured in Lighthouse scores and PageSpeed Insights reports.
What's the best alternative metric to FCP?
It depends on what you're measuring. If you want to know when the page feels *loaded* rather than just *started*, LCP is the better metric — it's also the one Google weights more heavily in Core Web Vitals. If you care about server performance specifically, TTFB isolates that. For interactivity, INP replaced FID in March 2024 as the Core Web Vital for responsiveness. There's no single replacement for FCP because it answers a specific question: how long does the user stare at a blank screen? We track FCP, LCP, and TTFB together on every project — they're complementary, not alternatives.
How do I improve a slow FCP score?
Start with the three biggest offenders. First, reduce render-blocking resources: move non-critical CSS out of the `<head>` and defer non-essential JavaScript with `async` or `defer`. Inlining critical CSS (the styles needed for above-the-fold content) typically shaves 200-500ms. Second, fix slow TTFB — if your server response is over 800ms, no front-end trick will get FCP under 1.8s. Consider edge caching (Vercel, Cloudflare) or static generation. Third, handle fonts properly: use `font-display: swap` and self-host with `next/font` or `@fontsource` to avoid the extra DNS lookup and connection to Google Fonts. We've seen these three fixes alone move FCP from 2.5s+ to under 1.2s on real projects.
Get in touch

Let's build
something together.

Whether it's a migration, a new build, or an SEO challenge — the Social Animal team would love to hear from you.

Get in touch →