First Contentful Paint (FCP)
First Contentful Paint (FCP) measures how long it takes for the first piece of content — text, image, SVG, or non-white canvas — to render on screen after the user requests a page. It's the moment users see the first sign that "this page is responding."
First Contentful Paint (FCP) measures how long it takes for the first piece of content — text, image, SVG, or non-white canvas — to render on screen after the user requests a page. It's the moment users see the first sign that "this page is responding."
Why It Matters
Users staring at a blank screen bounce fast. Nielsen Norman Group research shows attention drops sharply once the first visual response crosses 1 second. FCP isn't an official Core Web Vital today, but it's a key component of the Lighthouse performance score and a leading indicator for LCP. If FCP is slow, LCP can never be good.
Thresholds
| Rating | FCP |
|---|---|
| Good | ≤ 1.8s |
| Needs Improvement | 1.8–3.0s |
| Poor | > 3.0s |
Measured at the 75th percentile (p75) of real-user data from the Chrome User Experience Report.
TTFB → FCP → LCP → INP
Page loading is a timeline of sequential metrics.
- TTFB: Time until the server sends the first byte
- FCP: Time until the first content is painted
- LCP: Time until the largest content element is painted
- INP: Time until a user interaction visually responds
The ordering matters: if TTFB is slow, FCP can't be fast, and LCP can't be fast either. Performance work must start "from the top."
What Slows FCP Down
Slow TTFB: A slow server slows FCP by the same amount.
Render-blocking resources: External CSS and synchronous JS in <head> must download and execute before the browser can paint. Too many or too large, and FCP stalls.
Large DOM size: Thousands of elements in the initial HTML cost parse and layout time.
Web font loading: Custom fonts not yet loaded cause FOIT (flash of invisible text), making FCP feel delayed.
Client-side rendering (CSR): React and Vue apps that paint content only after downloading and executing the JS bundle push FCP back significantly.
How to Optimize
Improve TTFB: CDN, server-side caching, and DB optimization — the foundation.
Eliminate render-blocking resources: Use async and defer to defer JS. Inline critical CSS and load the rest asynchronously.
Server-side rendering (SSR): Use frameworks like Next.js, Astro, or Remix to pre-generate HTML on the server.
Font optimization: font-display: swap shows fallback text immediately while custom fonts load. Use preload for critical fonts only.
Shrink JS bundles: Tree shaking, code splitting, and removing unused libraries all lower the initial bundle.
Image optimization: <link rel="preload"> the hero image and serve WebP or AVIF.
Measurement Tools
- PageSpeed Insights: CrUX field data + lab data
- Lighthouse: Page-level diagnostics
- Chrome DevTools → Performance: FCP on the timeline
- web-vitals JS library: Collect real-user data on your own site
Sources: