Detecting First Contentful Paint (FCP) in Javascript

javascript
Published on December 23, 2020

First contentful paint (FCP) marks the time when browser renders some "content" on the screen for the given document. Content here refers to text, images (including background images), <svg> elements, or non-white <canvas> elements.

FCP happens only once during the page rendering cycle.

First contentful paint can be captured in native Javascript using PerformanceObserver & Paint Timing API.

const observer = new PerformanceObserver(function(entry_list) {
	for(const entry of entry_list.getEntriesByName('first-contentful-paint')) {
		console.log('First contentful painting done');
		
		console.log('FCP start time : ' + entry.startTime + ' milliseconds');
		console.log('FCP duration : ' + entry.duration + ' milliseconds');
	}
});

observer.observe({type: 'paint', buffered: true});

Browser Support : Chrome, Edge & Firefox (as of 23rd Dec 2020)

FCP Calculation As Per Google's Web Vitals

FCP calculation as per Google's Web Vitals is a bit different :

  • It ignores pages that are loaded in background tabs. FCP is considered only when page is in foreground the entire time.

    PerformanceObserver sends FCP report for pages in background tabs also.

  • It takes in account the situation when user clicks the back/forward buttons (where content may be served from browser cache).

    PerformanceObserver does not report FCP in such cases.

  • It takes in account the FCP of same-origin iframes present in the page, which may impact the final FCP (assuming iframes sends their FCP to the parent page).

    PerformanceObserver may not report FCP in such cases.

To handle the above cases and get metrics as per Google's consideration, the Web Vitals Javascript library can be used.

<script defer src="https://unpkg.com/web-vitals"></script>
<script>
addEventListener('DOMContentLoaded', function() {
	webVitals.getFCP(function(data) {
  		console.log('First contentful painting done');
  		console.log('FCP : ' + data.value + ' milliseconds');
	});
});
</script>
In this Tutorial