We're live-coding on Twitch! Join us!

Coined by Google, First Meaningful Paint is the time it takes for a page's primary content to appear on the screen. Often used as a primary metric for user-perceived loading experience, certain definitions of primary content differ depending on pages. It could be the headline and visible text for blog pages or search results for search engines as well.

Let’s say you’ve got an e-commerce page and there’s an image that is critical to the page, then first meaningful paint requires that image to be visible. Paints with only the page header, navigation bar, or loading indicator such as spinner icon don't qualify. First Contentful Paint is the time when some contentful thing (text, image, canvas, or SVG) is painted for the first time. It is used as an approximation of First Meaningful Paint but it often catches non-meaningful paints like headers and navigation bars.

A Visualization of FMP

A depiction of First Meaningful Paint by Rick Viscomi

In the illustration above, notice how the page is blank for the first ~1.0 second before the first paint event arrives - okay we’ve got the first paint, but as a reader looking for a news story, how “meaningful” is it? It isn’t until at ~2.0 seconds that the headline, section and author are visible that we can say we have got meaningful paint thus in the page above, the first meaningful paint is at 2 seconds.

Improving Your FMP

Implementing the concept of First Meaningful Paint on your web page might be tricky and daunting at first but with certain practices I will be listing below shortly you’ll find yourself good to go in no time.

This might seem unrealistic but you need to get that content to your users in approximately one second.

An average user’s mind starts wandering after this time window and they start thinking of how the competitor might have served them better. This is an insane number if you are a beginner but there is a way around it.

You can make a user feel at home and get comfortable using perceived performance strategies. This means you are not actually dishing out your real content, rather, you are creating an illusion of the content or showing the users some stale/cached data.

Load Images Progressively

You can create an illusion just like Medium does with images. You get a bite-sized poor image that is blurred and gives the user a perceived loading feel. This way, you do not have to render the entire image and make your content look uninteresting at load time. Taking a closer look at the average web page, it can be seen that its largest property is the image(s) it displays. These images can account for as much as 70% of the total size of the web page therefore it’s important to optimize your images as well as choose the right image format.

Another technique used by some sites is blur-up. This involves using small thumbnails as placeholders while the final image is still loading. Combined with lazy-loading, blur-up improves a user’s perceived performance while saving data traffic.

Here at Scotch, we implement lazy-loading using this JavaScript package: https://github.com/verlok/lazyload

Should you wish to check out more posts on image optimization, Cloudinary’s Blog has got a lot of detailed posts on this subject.

Service Workers and Caching

Most browsers are now adopting service workers so you can have a script running in your apps background to cache your content. A service worker is a script that is run by your browser in the background thus providing features that don’t need a web page or user interaction. The content is served from the cache when next the site is loaded. If done right, caches can reduce response times, decrease load on database, and save costs. There are several strategies and choosing the right one can make a big difference. Your caching strategy depends on the data and data access patterns. In other words, how the data is written and read. You can use a caching strategy to update the content after they have been rendered if they happen to have become stale.

Watch the Critical Rendering Path

Don’t let the terms fool you. The Critical Rendering Path simply means the journey the browsers takes to turn your HTML, CSS and JS into visual assets. Being aware of what happens during this journey will influence your decisions on performance. You might want to optimize critical rendering path as it will let users see "initial view content" quicker. Here’s how to optimize critical rendering path:

Minimize the number of critical resources

Critical resources are those that may block the initial rendering of a page. The fewer critical resources on a page, the less work the browser has to do to display the content on the screen. Critical resources can be minimized by eliminating them, deferring their download, or making them load asynchronously.

If you run Google PageSpeed, Google will likely tell you that any CSS or JS loaded in the <head> of your document is a render-blocking resource. Try to load JS at the bottom of your page and keep your CSS small.

Minimize the number of critical bytes

Minimize the amount of critical bytes by compressing and optimizing each resource. You can further optimize these resources by making use of HTML and CSS obfuscation. This can be done in a build setup where you minify your HTML/CSS/JS.

Finding a way to compress your images and optimize them is a good technique. You can usually save up to 70% of an image size without loss of quality.

Tools To Optimize Images

Minimize the critical path length

The critical path length is the number of round trips between the browser and the host of the assets (from request, to response, to retrieval). To shorten the critical path length or the number of round trips, download all critical resources as early as possible.

Tools to Test Your Site

  • Google PageSpeed Insights: Test your site and see what optimizations Google gives you. Try to get above an 80 on optimization.
  • WebPageTest: Test your site and see the waterfall of rendering. See which assets take up the most time for your loading.

Other Resources

Like this article? Follow @chris__sev on Twitter