FCP is measured from page navigation start to the first render of any DOM content in the viewport. The key word is "any" — text, an image, a background image rendered via CSS, an SVG, or an HTML canvas that's been painted. An empty white screen doesn't count; the browser has to actually paint something visible for FCP to fire.
It's distinct from TTFB (Time to First Byte), which measures when the first byte of the HTML response arrives. TTFB → FCP spans the time the browser takes to parse HTML, download render-blocking resources, and execute enough code to paint the first element. FCP is also distinct from LCP, which measures when the largest content element (usually a hero image or headline) paints. FCP often happens before LCP.
Key Takeaways
- FCP threshold: ≤1.8s is green, 1.8–3.0s is needs improvement, >3.0s is poor
- Render-blocking CSS and JavaScript are the most common causes of slow FCP — they delay the browser's first paint
- FCP is not a direct Core Web Vitals signal, but it contributes to Lighthouse's overall performance score (weighted at 10%)
- Slow TTFB causes slow FCP — you can't paint content until the HTML arrives
- FCP and LCP often share the same root causes; fixes for one usually improve the other
FCP vs TTFB vs LCP — What Each Measures
| Metric | Measures | Green threshold | CWV signal? |
|---|---|---|---|
| TTFB | Server response time — when first byte of HTML arrives | <800ms | No (diagnostic) |
| FCP | When first DOM content renders in browser | <1.8s | No (Lighthouse score input) |
| LCP | When largest visible content element renders | <2.5s | Yes (Core Web Vital) |
FCP happens first in the browser timeline, then LCP. A fast FCP signals that the page is responsive; a fast LCP signals that the main content is ready. If FCP is slow, LCP will almost certainly also be slow — the largest content element can't paint before the first content element does.
What Causes Slow FCP
Render-blocking resources. This is the most common cause. When a browser encounters a <link rel="stylesheet"> or a <script> without async/defer in the <head>, it stops parsing HTML and waits for that resource to download and execute before continuing. No HTML parsing = no DOM construction = no first paint.
The fix: add defer to non-critical scripts, move scripts to before </body>, or use async for scripts that don't depend on DOM order. For CSS: inline critical CSS for above-the-fold content; load non-critical CSS asynchronously with media="print" onload="this.media='all'".
Slow TTFB. FCP cannot happen until the HTML has arrived. A 2s TTFB means FCP cannot be below 2s regardless of other optimisations. Fix TTFB first: use a CDN, add server-side caching, optimise database queries, or migrate to a faster hosting tier. The bytewavenetwork Page Speed Inspector measures TTFB directly and breaks down where the delay occurs (DNS, TCP, TLS, or actual server processing).
Large HTML document. A browser must receive enough HTML to construct and paint the first visible element. If the above-the-fold content is 200KB into a 1MB HTML file, FCP waits until that content has arrived over the network. Solution: reduce server-side HTML payload, defer heavy server-rendered components, and avoid large JSON payloads embedded in HTML (common in Next.js hydration data).
Uncompressed responses. HTML served without gzip or brotli compression is significantly larger in transit. A 120KB uncompressed HTML document that compresses to 20KB takes 6× longer to download over a slow connection. Enabling compression at the server level is typically a one-line configuration change with an immediate effect on TTFB and FCP.
No CDN. A server in Frankfurt serving users in Sydney adds 200–300ms of network latency before any content arrives. A CDN caches content at edge nodes close to users. For static HTML pages, CDN delivery alone can move FCP from poor to good for geographically distant users.
Heavy web fonts. If the page's first render includes text, and that text uses a web font that hasn't loaded yet, the browser may delay painting the text (FOIT — Flash of Invisible Text) until the font arrives. Use font-display: swap to paint text immediately with the fallback font, which counts as FCP while the custom font loads in the background.
How to Diagnose Slow FCP
PageSpeed Insights (PSI). Runs a Lighthouse lab simulation and shows FCP in the metrics section. The "Opportunities" list shows which resources are render-blocking with their estimated time savings. The "Diagnostics" section shows critical request chains — the dependency graph of resources that must load before FCP fires.
Chrome DevTools Performance tab. Record a page load and look at the timeline. The "FCP" marker shows when the first paint occurred. Look at the network waterfall above it — which resources were loading when FCP fired? Which completed before FCP, indicating they blocked it? Which completed after, indicating they're candidates for deferral?
WebPageTest. Shows a filmstrip view of the page loading — frame by frame from blank screen to first paint. Makes the FCP moment visible rather than abstract.
ByteWaveNetwork Page Speed Inspector. Tests TTFB (broken into DNS/TCP/TLS/server), compression, and render-blocking resources in one pass. Render-blocking scripts and stylesheets are listed explicitly — each one is a candidate for deferral that directly improves FCP.
Prioritising FCP Fixes
The fastest path from red to green FCP for most sites:
1. Fix TTFB if it's over 600ms. Nothing else matters if the HTML takes a long time to arrive. Check server response time, CDN coverage, and compression. A TTFB above 800ms will almost certainly produce FCP above 1.8s on mobile connections.
2. Eliminate render-blocking scripts. Add defer to every script in the <head> that doesn't have it. Analytics tags (GA4, GTM), third-party scripts, and framework scripts are common offenders. The Page Speed Inspector lists render-blocking scripts by file name — add defer to each.
3. Inline critical CSS, defer the rest. The minimum CSS needed to render above-the-fold content should be inlined in a <style> block in <head>. The full stylesheet loads after FCP without blocking it. This is the single highest-impact FCP optimisation for CSS-heavy pages.
4. Enable compression. If your server isn't serving gzip or brotli, enabling it takes minutes and reduces HTML/CSS/JS transfer size by 60–85%. The Page Speed Inspector reports the compression algorithm (or lack of one) for the URL you test.
5. Add font-display: swap. If fonts are blocking text rendering, font-display: swap on all @font-face declarations allows the browser to paint text with the fallback font immediately. FCP fires on the fallback text, then the font swaps in when loaded.
Diagnose TTFB, Render-Blocking Resources, and Compression
Free, no signup. The Page Speed Inspector tests the specific issues that cause slow FCP — TTFB breakdown, render-blocking scripts, compression, and more — in one pass.
Try the Page Speed Inspector Free →Affiliate disclosure: Some links on this page may be affiliate links. We only mention tools we've personally used and have an honest opinion about. Affiliate revenue helps keep ByteWaveNetwork's tools free and maintained. We are not paid by any of the tools compared in this article for favorable coverage.