In web performance, what does First Contentful Paint (FCP) mark on a page load, what counts as "contentful" for it, and what does a good FCP still fail to tell you about the experience?
answer
- the moment the screen stops being blank
- text, image, canvas, SVG count
- a spinner satisfies it
- says nothing about useful content
- landmark between first byte and main content
basics
~20 sFirst Contentful Paint marks the moment the browser first renders any piece of DOM content — text, an image, a non-white canvas or an SVG. It proves the page has stopped being blank, but says nothing about whether the main content or anything usable has arrived.
solid answer
~50 sFCP is the timestamp of the first frame where the browser paints any content from the DOM: a run of text, an image (including a CSS background image), a non-white `<canvas>`, or an SVG. Before that instant the user is looking at a blank screen, so FCP is the honest answer to "has anything happened yet?". Current guidance calls under 1.8s good and over 3.0s poor at the 75th percentile. What it does *not* tell you is whether anything **useful** appeared — a spinner, a header bar or a skeleton placeholder all count as contentful, so a page can score a great FCP and still show the user nothing they came for. That is exactly why it is a supporting metric rather than a Core Web Vital: it is the lower bound of the loading story, useful mainly for separating "the page is blank" problems from "the main content is late" problems.
go deeper
Be able to state that FCP is when the browser first draws any DOM content and that before it the screen is blank. Name the qualifying content types and say plainly that a spinner counts.
Explain what sits between the first byte and the first paint — render-blocking stylesheets, head scripts, invisible font text, client-side rendering — and how each one delays the metric.
Show that you read FCP relatively, using its distance from TTFB and from the main-content metric to localize a slow load to server, network or render-blocking work rather than quoting it in isolation.
Be ready to argue about whether optimizing perceived start-of-load is worth the engineering it costs, and to set a policy on skeleton screens so teams do not report a metric win that no user experiences.
## The definition First Contentful Paint records the time from the start of the navigation to the first frame in which the browser paints **any** content originating from the DOM. "Contentful" is a specific list: - text nodes that are actually rendered (with a visible font), - `<img>` elements, and images painted as CSS backgrounds, - `<canvas>` elements that are not blank white, - SVG content. A background colour, a border, or an empty layout box does **not** count. Content inside a cross-document `<iframe>` is also not counted toward the parent document's FCP. ## Why the metric exists Before FCP the user is staring at a blank viewport with no evidence the click worked. FCP is the moment the page stops being blank. It answers exactly one question — *has the page started?* — and it answers it well. Everything about whether the page is *useful* belongs to other metrics. That modest scope is deliberate. FCP is a supporting metric, not a Core Web Vital. Teams use it as a checkpoint: a bad FCP means the problem is upstream of rendering entirely, and no amount of optimizing the main content will help until the first paint arrives. ## What sits in front of FCP FCP is bounded below by TTFB — nothing can be painted before bytes exist. After that, the classic delays are: 1. **Render-blocking resources.** A stylesheet referenced in the head must be downloaded and parsed before the browser will paint, because painting with unstyled content and then restyling would flash. A synchronous script in the head blocks parsing entirely. 2. **Web fonts.** Text whose font has not loaded yet may be held invisible during the font's block period, so it does not paint and does not count toward FCP. A page can have all its HTML and CSS ready and still show a blank screen waiting on a font file. 3. **Client-only rendering.** If the HTML response is an empty shell and the content is drawn by JavaScript, FCP cannot occur until that JavaScript is downloaded, parsed and executed — which is why the same page shipped with server-rendered HTML often has a dramatically better FCP with no other change. ## The thresholds and what they mean Current guidance treats FCP under 1.8 seconds as good and over 3.0 seconds as poor, evaluated at the 75th percentile of real users. Treat the shape of that guidance as more durable than the exact figures — the point is that a first paint arriving after roughly three seconds reads to a real user as a broken page, regardless of what the metric is called this year. ## The trap: FCP is easy to game Because *any* DOM content qualifies, FCP is the most gameable loading metric. Painting a loading spinner, a header bar, or a grey skeleton placeholder immediately produces an excellent FCP while the user learns nothing. This is not automatically dishonest — a skeleton genuinely does reassure people that something is happening — but it means an FCP number read on its own is not evidence of a fast page. The useful reading is always relative: - **FCP fast, LCP slow** → the shell renders promptly and the real content is late. Look at what the main content is waiting for. - **FCP slow, but close to TTFB** → the paint arrives almost as soon as bytes do; the front end is fine and the server is the problem. - **FCP slow with a fast TTFB** → the gap is render-blocking work: stylesheets, head scripts, fonts, or client-side rendering. That triangulation is the whole reason FCP is worth collecting. On its own it is a weak signal; as the middle landmark between TTFB and LCP it localizes a slow load to a specific stage. ## FCP versus "the page is ready" A final distinction interviewers listen for: FCP is a *rendering* milestone, not an *interactivity* one. The main thread can be completely saturated at the moment of first paint, so a page can paint quickly and then ignore every tap for two seconds. Metrics about responsiveness measure a different failure entirely, and a good FCP offers no protection against it.
- A page renders a grey skeleton placeholder immediately and loads its real content two seconds later. What does that do to FCP, and is it cheating?FCP fires as soon as the skeleton paints, so the number looks excellent. It is not automatically cheating — a skeleton genuinely tells the user the page is working — but it means FCP alone no longer describes the experience. You have to read it alongside the metric for the main content, or the improvement is purely cosmetic.
- Why can a page have all of its HTML and CSS in place and still not have reached FCP?Because text waiting on a web font may be held invisible during the font's block period, and invisible text paints nothing. Nothing else on screen may qualify as contentful — a background colour and empty boxes do not count — so the metric stays unfired until either the font arrives or a fallback face is swapped in.
- If a page's TTFB is 1.9s and its FCP is 2.1s, where would you spend effort?On the server or the network, not the browser. Only 200ms elapsed between the first byte and the first paint, so the rendering path is already efficient — there is almost nothing to reclaim there. The overwhelming majority of the wait was spent before the browser had anything to work with at all.
saying these in an interview costs you the question
- Thinks FCP means the main content has appeared
- Believes a background colour counts as contentful
- Treats FCP as a Core Web Vital
- Says a good FCP means the page is interactive
- Ignores render-blocking CSS and fonts as FCP causes