1 of 21

Largest Contentful Paint (LCP)

npm@ using images from maxlg@

2 of 21

Objective

Measure how long the main content of the website takes to be rendered on screen

3 of 21

Which content is considered?

  • Images, including background-images: first paint after loaded
  • Cohesive groups of text: first paint (even without webfonts loaded)

4 of 21

How is ‘main content’ determined?

We use largest element.

  • For image: size is visual size, may be reduced if clipped intrinsic size is smaller.
  • For text: best estimate the user agent can provide for the smallest rect containing the text nodes.

5 of 21

Pick the latest candidate found

LCP candidate 1

LCP candidate 2

Final LCP

6 of 21

When is LCP considered final?

We stop updating LCP when one of the following occurs:

  • Input (this is meant to be a page load metric), including scrolling.
  • Page unload (note: this can introduce abort bias).

7 of 21

Heuristics: removed elements

LCP uses some heuristics to ensure the algorithm chooses reasonable elements as the main content.

The most important one: the main content cannot be from a removed element.

8 of 21

Examples

9 of 21

10 of 21

11 of 21

12 of 21

13 of 21

14 of 21

15 of 21

Web Perf API for LCP?

  • We consider this an important page load metric, so we want developers to be able to measure it.
  • ElementTiming is related but not sufficient:
    • Hard to know when element occurs before user input
    • Hard to detect element removal
    • Element Timing does not guarantee that at least one entry is dispatched (note: this could be fixed for majority of websites by adjusting the threshold for implicit registration).

16 of 21

Idea 1: provide ‘before_user_input’

Add a bit to Element Timing entries saying if the element rendered before any user input.

  • Fixes the problem of knowing which entries should be considered for LCP.
  • Makes Element Timing more useful.
  • Does not fix the problem of discarding removed elements.

17 of 21

Idea 2: opting elements out

Allow developers to annotate that an element is NOT important, for example providing a specific keyword to elementtiming attribute.

  • Dedicated developers could annotate splash screens to opt out.
  • Not strictly needed: could filter out after receiving entries.
  • Analytics providers cannot do this, requires manual annotations.

18 of 21

Idea 3: Add ‘is_most_important’ bit

Whenever a new LCP candidate is found, dispatch an Element Timing entry with the ‘is_most_important’ bit set.

  • Developers can compute LCP easily by observing Element Timing.
  • Requires dispatching a new entry whenever a new LCP candidate is found.

19 of 21

Idea 4: use a new entryType for LCP

Whenever a new LCP candidate is found, dispatch a new LCP entry.

  • Developers can compute LCP by observing these entries.
  • Requires dispatching a full a new entry whenever a new LCP candidate is found.

20 of 21

Idea 5: Use the Reporting API

Expose LCP via the Reporting API.

  • LCP only needs to be exposed once.
  • Reporting API has very different use cases currently.
  • Cannot access LCP candidates via JS.

21 of 21

Idea 6: add getMostImportantElement()

Allow developer to query the most important element via a method (in Performance). Encourage developers to use only when they find a new input, or on the onhidden callback.

  • Developers can easily obtain the latest LCP at any time.
  • Encourages polling, goes against our principle of ‘use PerformanceObserver for everything’.