Google wants people to have a good web experience, so it ranks fast sites higher in search results. Of course, that’s a gross simplification but, presuming you’re comparing two sites with similar content and audiences, the faster one should appear higher in results. But how Google measures this has always been a bit of a guessing game, so it introduced Core Web Vitals to provide site owners and developers with some much-needed clarity.
Different tools return different sets of results and it can be difficult to know where to start.
Google’s Web Vitals initiative aims to simplify performance assessment and help you concentrate on the improvements which matter most. The Core Web Vitals are critical performance metrics which reflect real-world user experiences. Some are reported by the Lighthouse panel in Chrome DevTools, PageSpeed Insights, and the Google Search Console.
Google advises using the 75th percentile, i.e. record multiple results for the same metric, sort them into order from best to worst, then analyse the figure at the three-quarters point. Three out of four site visitors will therefore experience that level of performance.
The current Core Web Vitals are Largest Contentful Paint, First Input Delay, and Cumulative Layout Shift which assess loading, interactivity, and visual stability accordingly.
Largest Contentful Paint (LCP)
LCP measures loading performance — how quickly content appears.
Historic metrics such as page load and
DOMContentLoaded have struggled in this respect because they are not always indicative of the user experience. For example, a splash screen could appear almost instantly but usable content loaded by further Ajax requests could take much longer to appear.
Largest Contentful Paint (LCP) reports the render time of the largest image or text block visible within the viewport. A time under 2.5 seconds is considered good and anything above 4.0 seconds is considered poor.
The element types considered in LCP are:
<image>elements inside an
- the poster image of a
- an element with a background image loaded using the CSS
- block-level elements containing text nodes.
The largest element is determined as the content loads and the size is calculated to be its visible dimensions in the browser viewport.
LCP can be affected by:
- server response times
- resource loading times
- client-size processing times
LCP improvements may be possible by:
- using a Content Delivery Network (CDN) to route requests to closer servers
- optimizing the server response by minimizing the number of expensive render-time processes
- minimizing the file size of assets
- caching assets locally, and perhaps using a service worker to return the local version first.
First Input Delay (FID)
FID measures responsiveness — how quickly a page responds to a user’s action.
This metric records the time from when a user interacts with the page (clicks, taps, key presses, etc.) to the time the browser begins processing that event handler. A delay of less than 100ms is considered good and anything above 300ms is considered poor.
FID can only be accurately measured when an application is served to a real user. Additionally, it only measures the delay in event processing — not the time taken to run a handler or update the UI.
Google and various tools therefore use Total Blocking Time (TBT) as an alternative metric which can be calculated without real user input. TBT measures the total time between:
- the First Contentful Paint (FCP) — the time when any part of the page’s content has been rendered, and
- the Time to Interactive (TTI) — the time when the page is capable of reliably responding to user input (no long tasks are running and no more than two GET requests are yet to be resolved).
FID/TBT improvements may be possible by:
- breaking-up long-running tasks
- using web workers to run tasks in a background thread
Cumulative Layout Shift (CLS)
CLS measures visual stability — the unexpected movement of content when viewing a page.
CLS assesses those annoying situations when content moves without warning — typically when the DOM changes after an advertisement or image above your current scroll position completes loading. The problem is especially pronounced on mobile devices and can cause you to lose your place or tap the wrong link.
CLS is calculated by multiplying:
- The impact fraction: the total area of unstable elements in the viewport (those which will move). An impact fraction of 0.5 indicates that elements totalling half the viewport will be displaced.
- The distance fraction: the greatest distance moved by any single element within the viewport. A distance fraction of 0.25 indicates that at least one element moved by a quarter of the viewport (horizontally or vertically).
Consider the following example which loads an advertisement shortly after the logo, menu, and hero image have been rendered:
The logo and menu do not move — they are stable elements. The advertisement is added to the DOM and it’s starting position does not change so it is also stable. However, the hero image will move:
- The hero is 360 x 510 pixels in a 360 x 720 viewport. It’s impact fraction is therefore (360 x 510) / (360 x 720) = 0.71
- It moves by 90 vertical pixels in the 720px viewport height, so it’s distance fraction is 90 / 720 = 0.125
The CLS is therefore 0.71 x 0.125 = 0.089
A CLS score under 0.1 is considered good and anything above 0.25 is considered poor. In this case, the CLS is just within the accepted range because, although a large area is affected, it is moved a relatively small distance. A larger advertisement would require further attention, though.
The CLS algorithm does not record the layout shift for 500ms after any user interaction which could trigger a UI change or viewport resize. Therefore, your page will not be penalized for interface updates, transitions, and animations which are necessary for operation, e.g. opening a full-screen menu from a hamburger icon.
The Rendering panel in Chrome DevTools (menu > More tools > Rendering) provides a Layout Shift Regions option. Check the box and refresh the page — layout shifts are highlighted in blue. You can also modify the network speed in the Network panel to slow down loading.
FID/TBT improvements may be possible by:
- reserving space for images, videos, and iframe elements by adding dimensions with
heightattributes, the CSS
aspect-ratioproperty, or the old padding trick as appropriate
- avoiding FOUT (Flash of Unstyled Text) and FOIT (Flash of Invisible Text) when loading web fonts. Preloading or using similarly-sized fallback fonts will help
- not inserting DOM elements above existing content during the initial page load, e.g. newsletter sign-up and similar notice boxes
- using CSS
opacityfor less-costly animations.
Core Web Vitals will evolve over time but assessing LCP, FID, and CLS metrics can help identify the most critical issues. Tackle the quick and easy problems first — they often have the biggest return on investment:
- activate server compression and HTTP/2 or HTTP/3
- ensure browser caching is used by setting HTTP expiry headers
- preload assets early
- remove unused assets
- consider using a CDN or better hosting
- use appropriate image sizes and formats
- optimize image and video file sizes (a specialist CDN can help)
The SitePoint book Jump Start Web Performance provides dozens of tips to improve site speed, reduce costs, and keep users happy.