Lighthouse audit first-contentful-paint · Performance

First Contentful Paint (FCP): what it is and how to fix it

View raw .md for LLMs / your notes
Quick answer: First Contentful Paint measures when the first text or image appears on screen. A good FCP is under 1.8 seconds. Improve it by cutting server response time, removing render-blocking CSS and JavaScript, preconnecting to critical origins, and using font-display swap. FCP happens before LCP and gates it.

FCP measures the time from navigation start to when the browser paints the first piece of content: text, an image, a non-blank canvas. It is the user's first signal that the page is actually loading.

TL;DR

What is First Contentful Paint (FCP)?

FCP is the gap between the request starting and the first DOM content paint. It comes before LCP: FCP is "something appeared," LCP is "the main thing appeared." A slow FCP almost always drags LCP with it, so fixing FCP is upstream leverage.

Why does First Contentful Paint matter?

FCP is the first moment a user stops looking at a blank screen. Pages with slow FCP feel broken even when they eventually load fast. It also gates every later metric: nothing meaningful paints until the first paint happens.

What causes slow FCP and how do I fix it?

1. Slow server response (TTFB)

Nothing renders until the first bytes arrive. If time to first byte is high, FCP cannot be fast.

2. Render-blocking CSS and JavaScript

The browser will not paint until it has processed blocking CSS in <head> and any synchronous scripts before content.

<!-- Inline the critical above-the-fold CSS -->
<style>/* critical CSS here */</style>

<!-- Load the rest non-blocking -->
<link rel="preload" href="/styles.css" as="style" onload="this.rel='stylesheet'" />

<!-- Defer scripts -->
<script src="/app.js" defer></script>

3. No early connection to critical origins

If your fonts, hero image, or critical API live on another origin, the browser pays DNS + TCP + TLS before it can fetch them.

<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="preconnect" href="https://cdn.example.com" />

4. Web fonts blocking text

With the default font-display: auto, text can stay invisible until the font downloads (flash of invisible text), delaying FCP.

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

Preload the one or two fonts used above the fold.

What are common FCP mistakes?

How do I improve FCP in Next.js, SPAs, or WordPress?

How do I verify FCP improved?

  1. Re-run Lighthouse: FCP should drop under 1.8 s on the mobile profile.
  2. DevTools → Performance → record a load → read the FCP marker.
  3. Check field data in Search Console / CrUX: lab FCP improving should track with real users over a few weeks.
  4. Confirm LCP and TBT did not regress while changing the critical path.

Related audits


Audit your URL at https://lighthouse-md.com.

Audit your page now

Paste your URL, get scores plus a CLAUDE.md plan for Claude Code.

Run audit →