First Contentful Paint (FCP)

The moment the browser paints the first bit of real content and the blank white screen ends. Under 1.8 seconds passes.

when something finally shows upthe first thing you seeFCPfirst paintwhite screen timefirst contentfull painthow long the page stays blankblank screen before the page appears

See it

Live demo coming soon

What it is

FCP marks the moment the browser paints the first piece of real content: any text, image, SVG, or non-blank canvas. It ends the white screen. Under 1.8s is a pass, over 3s is a fail. Unlike LCP, it does not care whether the thing painted is useful, only that something appeared.

What delays it is almost always the same short list: a slow TTFB, render-blocking stylesheets and synchronous scripts in the head, and an HTML shell with no content in it. The fixes are inline critical CSS for the first screen, defer or async everything else, preconnect to the font and API origins, and ship actual server-rendered markup instead of an empty root div.

Gotcha: a spinner can count, and so can a skeleton screen, but only if what paints is qualifying content: text, an image, an SVG, a non-blank canvas. A skeleton built purely from CSS backgrounds on empty divs may paint nothing FCP recognises, and a CSS-only spinner is in the same boat. Either way you can drive FCP down while the user still has nothing to read, which is exactly why LCP exists alongside it. Use FCP as the diagnostic for 'how long am I blank' and LCP as the answer to 'how long until it is useful'. Font loading is the subtle one: font-display: block hides text until the webfont arrives, so your headline can miss FCP entirely.

Ask AI for it

Speed up First Contentful Paint on this page. Inline the critical CSS for the first screen in the <head> and load the rest of the stylesheet asynchronously; move every non-essential script to defer, async, or an idle callback so nothing synchronous sits in the head; add preconnect for font and asset origins and preload the fonts used above the fold with font-display: swap; and make sure the server sends real markup for the first screen rather than an empty root element hydrated later. Do not fake the win with a spinner. Target FCP under 1.8s on a throttled 4G mid-range phone and list what was render-blocking before.

You might have meant

largest contentful painttime to first byterender blocking resourcecritical csscore web vitals

Go deeper