diff --git a/files/en-us/_redirects.txt b/files/en-us/_redirects.txt index 94d43660985e10a..e1eb1b36e95d9fb 100644 --- a/files/en-us/_redirects.txt +++ b/files/en-us/_redirects.txt @@ -8732,6 +8732,7 @@ /en-US/docs/Web/API/KeyframeEffectReadOnly/getKeyframes /en-US/docs/Web/API/KeyframeEffect/getKeyframes /en-US/docs/Web/API/KeyframeEffectReadOnly/iterationComposite /en-US/docs/Web/API/KeyframeEffect/iterationComposite /en-US/docs/Web/API/KeyframeEffectReadOnly/target /en-US/docs/Web/API/KeyframeEffect/target +/en-US/docs/Web/API/Largest_Contentful_Paint_API /en-US/docs/Web/API/LargestContentfulPaint /en-US/docs/Web/API/LinearAccelerationSensor/x /en-US/docs/Web/API/Accelerometer/x /en-US/docs/Web/API/LinearAccelerationSensor/y /en-US/docs/Web/API/Accelerometer/y /en-US/docs/Web/API/LinearAccelerationSensor/z /en-US/docs/Web/API/Accelerometer/z diff --git a/files/en-us/glossary/first_contentful_paint/index.md b/files/en-us/glossary/first_contentful_paint/index.md index 9adfbe73f33db06..2cb03e5f48de3e3 100644 --- a/files/en-us/glossary/first_contentful_paint/index.md +++ b/files/en-us/glossary/first_contentful_paint/index.md @@ -15,6 +15,6 @@ _The First Contentful Paint_ time stamp is when the browser first rendered any t - [First paint](/en-US/docs/Glossary/First_paint) - [`PerformancePaintTiming`](/en-US/docs/Web/API/PerformancePaintTiming) -- [Largest Contentful API](/en-US/docs/Web/API/Largest_Contentful_Paint_API) +- [Largest Contentful Paint](/en-US/docs/Glossary/Largest_contentful_paint) - [First meaningful paint](/en-US/docs/Glossary/first_meaningful_paint) - [First Contentful Paint](https://web.dev/fcp/) at web.dev diff --git a/files/en-us/glossary/first_paint/index.md b/files/en-us/glossary/first_paint/index.md index cfeea26335b759c..8070b770b3be651 100644 --- a/files/en-us/glossary/first_paint/index.md +++ b/files/en-us/glossary/first_paint/index.md @@ -13,5 +13,5 @@ tags: - [First contentful paint](/en-US/docs/Glossary/First_contentful_paint) - [`PerformancePaintTiming`](/en-US/docs/Web/API/PerformancePaintTiming) -- [Largest Contentful API](/en-US/docs/Web/API/Largest_Contentful_Paint_API) +- [Largest Contentful Paint](/en-US/docs/Glossary/Largest_contentful_paint) - [First meaningful paint](/en-US/docs/Glossary/first_meaningful_paint) diff --git a/files/en-us/glossary/largest_contentful_paint/index.md b/files/en-us/glossary/largest_contentful_paint/index.md new file mode 100644 index 000000000000000..38e88f32c01362e --- /dev/null +++ b/files/en-us/glossary/largest_contentful_paint/index.md @@ -0,0 +1,24 @@ +--- +title: Largest contentful paint +slug: Glossary/Largest_contentful_paint +tags: + - Performance + - Reference + - Web Performance +--- + +The **Largest Contentful Paint** (LCP) performance metric provides the render time of the largest image or text block visible within the viewport, recorded from when the page first begins to load. + +The following elements are considered when determining the LCP: + +- {{HTMLElement("img")}} elements. +- [``](/en-US/docs/Web/SVG/Element/image) elements inside an SVG. +- The poster images of {{HTMLElement("video")}} elements. +- Elements with a {{cssxref("background-image")}}. +- Groups of text nodes, such as {{HTMLElement("p")}}. + +## See also + +- [`LargestContentfulPaint`](/en-US/docs/Web/API/LargestContentfulPaint) +- [First contentful paint](/en-US/docs/Glossary/First_contentful_paint) +- [First paint](/en-US/docs/Glossary/First_paint) diff --git a/files/en-us/web/api/largest_contentful_paint_api/index.md b/files/en-us/web/api/largest_contentful_paint_api/index.md deleted file mode 100644 index 78eb1327728a071..000000000000000 --- a/files/en-us/web/api/largest_contentful_paint_api/index.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: Largest Contentful Paint API -slug: Web/API/Largest_Contentful_Paint_API -page-type: web-api-overview -tags: - - API - - Largest Contentful Paint API - - LargestContentfulPaint - - Landing - - Overview - - Reference - - Experimental -browser-compat: api.LargestContentfulPaint ---- - -{{DefaultAPISidebar("Performance API")}}{{SeeCompatTable}} - -The **Largest Contentful Paint API** provides [perceived performance](/en-US/docs/Learn/Performance/Perceived_performance) data that allows you to know exactly how long a user waits, after navigating to your page, before seeing the main content of the page in their browser viewport — in contrast to just knowing when the user can first see a loading indicator or background image or other such initial/early-loading content (which is what the related [Paint Timing API](/en-US/docs/Web/API/Paint_Timing_API) provides). - -## Concepts and Usage - -The key principle underlying the Largest Contentful Paint API is that by having data to help you minimize the time that users have to wait before they can see the site's main content, you can make the site feel more engaging and responsive (better performing) for your users. - -See the [perceived performance](/en-US/docs/Learn/Performance/Perceived_performance) article for an introduction to the core concepts underlying both the Largest Contentful Paint API and the [Paint Timing API](/en-US/docs/Web/API/Paint_Timing_API). - -The Largest Contentful Paint metric provides the render time of the largest image or text block visible within the viewport, recorded from when the page first begins to load. The API supports the following elements: - -- {{HTMLElement("img")}} elements. -- [``](/en-US/docs/Web/SVG/Element/image) elements inside an SVG. -- The poster images of {{HTMLElement("video")}} elements. -- Elements with a {{cssxref("background-image")}}. -- Groups of text nodes, such as {{HTMLElement("p")}}. - -## Interfaces - -- {{domxref("LargestContentfulPaint")}} - - : Reports details about the largest image or text paint before user input on a web page. - -## Examples - -The following example shows an image and a large paragraph of text. An observer is registered to get the largest contentful paint while the page is loading. - -```html - -

This is large body of text.

-``` - -```js -const observer = new PerformanceObserver((list) => { - let perfEntries = list.getEntries(); - let lastEntry = perfEntries[perfEntries.length - 1]; - // Process the latest candidate for largest contentful paint -}); -observer.observe({entryTypes: ['largest-contentful-paint']}); -``` - -## Specifications - -{{Specifications}} - -## Browser compatibility - -{{Compat}} - -## See also - -- [Perceived performance](/en-US/docs/Learn/Performance/Perceived_performance) -- [Largest Contentful Paint](https://web.dev/lcp/) at web.dev -- [Optimize Largest Contentful Paint](https://web.dev/optimize-lcp/) at web.dev -- [User-centric performance metrics](https://web.dev/user-centric-performance-metrics/#types-of-metrics) at web.dev -- [Largest Contentful Paint in Lighthouse](https://web.dev/lighthouse-largest-contentful-paint/) diff --git a/files/en-us/web/api/largestcontentfulpaint/element/index.md b/files/en-us/web/api/largestcontentfulpaint/element/index.md index 5806c2bdaf6bb80..815e7cc592d4a93 100644 --- a/files/en-us/web/api/largestcontentfulpaint/element/index.md +++ b/files/en-us/web/api/largestcontentfulpaint/element/index.md @@ -22,23 +22,17 @@ An {{domxref("Element")}}. ## Examples -The following example gets the `LargestContentfulPaint` object and prints the value of `element` to the console. +### Logging the largest contentful paint element -```js -try { - let lcp; - - const po = new PerformanceObserver((entryList) => { - const entries = entryList.getEntries(); - const lastEntry = entries[entries.length - 1]; - console.log(lastEntry.element); - }); +This example uses a {{domxref("PerformanceObserver")}} notifying of new `largest-contentful-paint` performance entries as they are recorded in the browser's performance timeline. The `buffered` option is used to access entries from before the observer creation. - po.observe({type: 'largest-contentful-paint', buffered: true}); - -} catch (e) { - // Do nothing if the browser doesn't support this API. -} +```js +const observer = new PerformanceObserver((list) => { + const entries = list.getEntries(); + const lastEntry = entries[entries.length - 1]; // Use the latest LCP candidate + console.log(lastEntry.element); +}); +observer.observe({ type: "largest-contentful-paint", buffered: true }); ``` ## Specifications diff --git a/files/en-us/web/api/largestcontentfulpaint/id/index.md b/files/en-us/web/api/largestcontentfulpaint/id/index.md index 48800943ab59a8c..dc94b94e03653ed 100644 --- a/files/en-us/web/api/largestcontentfulpaint/id/index.md +++ b/files/en-us/web/api/largestcontentfulpaint/id/index.md @@ -18,27 +18,21 @@ The **`id`** read-only property of the {{domxref("LargestContentfulPaint")}} int ## Value -A string containing the ID of the element. +A string containing the ID of the element, or the empty string if there is no such ID. ## Examples -The following example gets the `LargestContentfulPaint` object and prints the value of `id` to the console. +### Logging the largest contentful paint element ID -```js -try { - let lcp; - - const po = new PerformanceObserver((entryList) => { - const entries = entryList.getEntries(); - const lastEntry = entries[entries.length - 1]; - console.log(lastEntry.id); - }); +This example uses a {{domxref("PerformanceObserver")}} notifying of new `largest-contentful-paint` performance entries as they are recorded in the browser's performance timeline. The `buffered` option is used to access entries from before the observer creation. - po.observe({type: 'largest-contentful-paint', buffered: true}); - -} catch (e) { - // Do nothing if the browser doesn't support this API. -} +```js +const observer = new PerformanceObserver((list) => { + const entries = list.getEntries(); + const lastEntry = entries[entries.length - 1]; // Use the latest LCP candidate + console.log(lastEntry.id); +}); +observer.observe({ type: "largest-contentful-paint", buffered: true }); ``` ## Specifications diff --git a/files/en-us/web/api/largestcontentfulpaint/index.md b/files/en-us/web/api/largestcontentfulpaint/index.md index 4e7faab753fcd42..52aef977ed11bd9 100644 --- a/files/en-us/web/api/largestcontentfulpaint/index.md +++ b/files/en-us/web/api/largestcontentfulpaint/index.md @@ -16,13 +16,43 @@ browser-compat: api.LargestContentfulPaint {{APIRef("Performance API")}}{{SeeCompatTable}} -The `LargestContentfulPaint` interface of the {{domxref("Largest Contentful Paint API")}} provides details about the largest image or text paint before user input on a web page. The timing of this paint is a good heuristic for when the main page content is available during load. +The `LargestContentfulPaint` interface provides timing information about the largest image or text paint before user input on a web page. + +## Description + +The key moment this API provides is the {{Glossary("Largest Contentful Paint")}} (LCP) metric. It provides the render time of the largest image or text block visible within the viewport, recorded from when the page first begins to load. The following elements are considered when determining the LCP: + +- {{HTMLElement("img")}} elements. +- [``](/en-US/docs/Web/SVG/Element/image) elements inside an SVG. +- The poster images of {{HTMLElement("video")}} elements. +- Elements with a {{cssxref("background-image")}}. +- Groups of text nodes, such as {{HTMLElement("p")}}. + +To measure render times of other elements, use the {{domxref("PerformanceElementTiming")}} API. + +Additional key paint moments are provided by the {{domxref("PerformancePaintTiming")}} API: + +- {{Glossary("First paint")}} (FP): Time when anything is rendered. Note that the marking of the first paint is optional, not all user agents report it. +- {{Glossary("First contentful paint")}} (FCP): Time when the first bit of DOM text or image content is rendered. + +`LargestContentfulPaint` inherits from {{domxref("PerformanceEntry")}}. {{InheritanceDiagram}} ## Instance properties -_This interface also inherits properties from {{domxref("PerformanceEntry")}}._ +This interface extends the following {{domxref("PerformanceEntry")}} properties by qualifying and constraining the properties as follows: + +- {{domxref("PerformanceEntry.entryType")}} {{ReadOnlyInline}} {{Experimental_Inline}} + - : Returns "`largest-contentful-paint`". +- {{domxref("PerformanceEntry.name")}} {{ReadOnlyInline}} {{Experimental_Inline}} + - : Always returns an empty string. +- {{domxref("PerformanceEntry.startTime")}} {{ReadOnlyInline}} {{Experimental_Inline}} + - : Returns the value of this entry's {{domxref("LargestContentfulPaint.renderTime", "renderTime")}} if it is not `0`, otherwise the value of this entry's {{domxref("LargestContentfulPaint.loadTime", "loadTime")}}. +- {{domxref("PerformanceEntry.duration")}} {{ReadOnlyInline}} {{Experimental_Inline}} + - : Returns `0`, as `duration` is not applicable to this interface. + +It also supports the following properties: - {{domxref("LargestContentfulPaint.element")}} {{ReadOnlyInline}} {{Experimental_Inline}} - : The element that is the current largest contentful paint. @@ -46,40 +76,38 @@ _This interface also inherits methods from {{domxref("PerformanceEntry")}}._ ## Examples -The following example shows how to create a {{domxref('PerformanceObserver')}} that listens for `largest-contentful-paint` entries and logs the LCP value to the console. +### Observing the largest contentful paint + +In the following example, an observer is registered to get the largest contentful paint while the page is loading. The `buffered` flag is used to access data from before observer creation. + +The LCP API analyzes all content it finds (including content that is removed from the DOM). When new largest content is found, it creates a new entry. It stops searching for larger content when scroll or input events occur, since these events likely introduce new content on the website. Thus the LCP is the last performance entry reported by the observer. + +```js +const observer = new PerformanceObserver((list) => { + const entries = list.getEntries(); + const lastEntry = entries[entries.length - 1]; // Use the latest LCP candidate + console.log("LCP:", lastEntry.startTime); + console.log(lastEntry); +}); +observer.observe({ type: "largest-contentful-paint", buffered: true }); +``` + +### Cross-origin image render time + +For security reasons, the value of the {{domxref("LargestContentfulPaint.renderTime", "renderTime")}} property is `0` if the resource is a cross-origin request. Instead the {{domxref("LargestContentfulPaint.loadTime", "loadTime")}} is exposed. To expose cross-origin render time information, the {{HTTPHeader("Timing-Allow-Origin")}} HTTP response header needs to be set. + +For example, to allow `https://developer.mozilla.org` to see `renderTime`, the cross-origin resource should send: + +```http +Timing-Allow-Origin: https://developer.mozilla.org +``` -This example also demonstrates how to include buffered entries (those that ocurred before `observer()` was called), which is done by setting the `buffered` option to `true`. +Like in the code example, you can use {{domxref("PerformanceEntry.startTime", "startTime")}}, which returns the value of the entry's {{domxref("LargestContentfulPaint.renderTime", "renderTime")}} if it is not `0`, and otherwise the value of this entry's {{domxref("LargestContentfulPaint.loadTime", "loadTime")}}. However, it is recommended to set the {{HTTPHeader("Timing-Allow-Origin")}} header so that the metrics will be more accurate. -Note that in this example data is only sent to the server when the user leaves the tab. +If you use `startTime`, you can flag any inaccuracies by checking if `renderTime` was used: ```js -// Catch errors since some browsers throw when using the new `type` option. -// https://bugs.webkit.org/show_bug.cgi?id=209216 -try { - let lcp; - - const po = new PerformanceObserver((entryList) => { - const entries = entryList.getEntries(); - const lastEntry = entries[entries.length - 1]; - - // Update `lcp` to the latest value, using `renderTime` if it's available, - // otherwise using `loadTime`. (Note: `renderTime` may not be available on - // image elements loaded cross-origin without the `Timing-Allow-Origin` header.) - lcp = lastEntry.renderTime || lastEntry.loadTime; - }); - - po.observe({type: 'largest-contentful-paint', buffered: true}); - - // Send data to the server. - addEventListener('visibilitychange', function fn() { - if (lcp && document.visibilityState === 'hidden') { - console.log('LCP:', lcp); - removeEventListener('visibilitychange', fn, true); - } - }, true); -} catch (e) { - // Do nothing if the browser doesn't support this API. -} +const isAccurateLCP = entry.renderTime ? true : false; ``` ## Specifications @@ -92,5 +120,6 @@ try { ## See also -- [Largest Contentful Paint (LCP)](https://web.dev/lcp/) -- [LCP in Lighthouse](https://web.dev/lighthouse-largest-contentful-paint/) +- {{Glossary("Largest Contentful Paint")}} +- {{Glossary("First contentful paint")}} +- {{Glossary("First paint")}} diff --git a/files/en-us/web/api/largestcontentfulpaint/loadtime/index.md b/files/en-us/web/api/largestcontentfulpaint/loadtime/index.md index 7820b8b7a213a95..58c4f39950a2650 100644 --- a/files/en-us/web/api/largestcontentfulpaint/loadtime/index.md +++ b/files/en-us/web/api/largestcontentfulpaint/loadtime/index.md @@ -22,23 +22,17 @@ A {{domxref("DOMHighResTimeStamp","timestamp")}} representing the time in millis ## Examples -The following example gets the `LargestContentfulPaint` object and prints the value of `loadTime` to the console. +### Logging the loadTime of the largest contentful paint -```js -try { - let lcp; - - const po = new PerformanceObserver((entryList) => { - const entries = entryList.getEntries(); - const lastEntry = entries[entries.length - 1]; - console.log(lastEntry.loadTime); - }); +This example uses a {{domxref("PerformanceObserver")}} notifying of new `largest-contentful-paint` performance entries as they are recorded in the browser's performance timeline. The `buffered` option is used to access entries from before the observer creation. - po.observe({type: 'largest-contentful-paint', buffered: true}); - -} catch (e) { - // Do nothing if the browser doesn't support this API. -} +```js +const observer = new PerformanceObserver((list) => { + const entries = list.getEntries(); + const lastEntry = entries[entries.length - 1]; // Use the latest LCP candidate + console.log(lastEntry.loadTime); +}); +observer.observe({ type: "largest-contentful-paint", buffered: true }); ``` ## Specifications diff --git a/files/en-us/web/api/largestcontentfulpaint/rendertime/index.md b/files/en-us/web/api/largestcontentfulpaint/rendertime/index.md index 543cac273a48ae6..a2f30e0f3529fa2 100644 --- a/files/en-us/web/api/largestcontentfulpaint/rendertime/index.md +++ b/files/en-us/web/api/largestcontentfulpaint/rendertime/index.md @@ -18,27 +18,42 @@ The **`renderTime`** read-only property of the {{domxref("LargestContentfulPaint ## Value -A {{domxref("DOMHighResTimeStamp","timestamp")}} representing the time in milliseconds that the element was rendered to the screen. +The `renderTime` property can have the following values: + +- A {{domxref("DOMHighResTimeStamp","timestamp")}} representing the time in milliseconds that the element was rendered to the screen. +- `0` if the resource is a cross-origin request and no {{HTTPHeader("Timing-Allow-Origin")}} HTTP response header is used. ## Examples -The following example gets the `LargestContentfulPaint` object and prints the value of `renderTime` to the console. +### Logging the renderTime of the largest contentful paint + +This example uses a {{domxref("PerformanceObserver")}} notifying of new `largest-contentful-paint` performance entries as they are recorded in the browser's performance timeline. The `buffered` option is used to access entries from before the observer creation. ```js -try { - let lcp; +const observer = new PerformanceObserver((list) => { + const entries = list.getEntries(); + const lastEntry = entries[entries.length - 1]; // Use the latest LCP candidate + console.log(lastEntry.renderTime); +}); +observer.observe({ type: "largest-contentful-paint", buffered: true }); +``` - const po = new PerformanceObserver((entryList) => { - const entries = entryList.getEntries(); - const lastEntry = entries[entries.length - 1]; - console.log(lastEntry.renderTime); - }); +### Cross-origin image render time - po.observe({type: 'largest-contentful-paint', buffered: true}); +For security reasons, the value of the {{domxref("LargestContentfulPaint.renderTime", "renderTime")}} property is `0` if the resource is a cross-origin request. Instead the {{domxref("LargestContentfulPaint.loadTime", "loadTime")}} is exposed. To expose cross-origin render time information, the {{HTTPHeader("Timing-Allow-Origin")}} HTTP response header needs to be set. -} catch (e) { - // Do nothing if the browser doesn't support this API. -} +For example, to allow `https://developer.mozilla.org` to see `renderTime`, the cross-origin resource should send: + +```http +Timing-Allow-Origin: https://developer.mozilla.org +``` + +Alternatively, you can use {{domxref("PerformanceEntry.startTime", "startTime")}} which returns the value of the entry's {{domxref("LargestContentfulPaint.renderTime", "renderTime")}} if it is not `0`, and otherwise the value of this entry's {{domxref("LargestContentfulPaint.loadTime", "loadTime")}}. However, it is recommended to set the {{HTTPHeader("Timing-Allow-Origin")}} header so that the metrics will be more accurate. + +If you use `startTime`, you can flag any inaccuracies by checking if `renderTime` was used: + +```js +const isAccurateLCP = entry.renderTime ? true : false; ``` ## Specifications diff --git a/files/en-us/web/api/largestcontentfulpaint/size/index.md b/files/en-us/web/api/largestcontentfulpaint/size/index.md index 7f8dd6df46cb6ef..52c20f25844183b 100644 --- a/files/en-us/web/api/largestcontentfulpaint/size/index.md +++ b/files/en-us/web/api/largestcontentfulpaint/size/index.md @@ -24,23 +24,17 @@ An integer representing the width times height of the element. ## Examples -The following example gets the `LargestContentfulPaint` object and prints the value of `size` to the console. +### Logging the size of the largest contentful paint element -```js -try { - let lcp; - - const po = new PerformanceObserver((entryList) => { - const entries = entryList.getEntries(); - const lastEntry = entries[entries.length - 1]; - console.log(lastEntry.size); - }); +This example uses a {{domxref("PerformanceObserver")}} notifying of new `largest-contentful-paint` performance entries as they are recorded in the browser's performance timeline. The `buffered` option is used to access entries from before the observer creation. - po.observe({type: 'largest-contentful-paint', buffered: true}); - -} catch (e) { - // Do nothing if the browser doesn't support this API. -} +```js +const observer = new PerformanceObserver((list) => { + const entries = list.getEntries(); + const lastEntry = entries[entries.length - 1]; // Use the latest LCP candidate + console.log(lastEntry.size); +}); +observer.observe({ type: "largest-contentful-paint", buffered: true }); ``` ## Specifications diff --git a/files/en-us/web/api/largestcontentfulpaint/url/index.md b/files/en-us/web/api/largestcontentfulpaint/url/index.md index 0a6ed10ef785071..a7098c63b8b82f8 100644 --- a/files/en-us/web/api/largestcontentfulpaint/url/index.md +++ b/files/en-us/web/api/largestcontentfulpaint/url/index.md @@ -22,23 +22,17 @@ A string containing a URL. ## Examples -The following example gets the `LargestContentfulPaint` object and prints the value of `url` to the console. +### Logging the url of the largest contentful paint -```js -try { - let lcp; - - const po = new PerformanceObserver((entryList) => { - const entries = entryList.getEntries(); - const lastEntry = entries[entries.length - 1]; - console.log(lastEntry.url); - }); +This example uses a {{domxref("PerformanceObserver")}} notifying of new `largest-contentful-paint` performance entries as they are recorded in the browser's performance timeline. The `buffered` option is used to access entries from before the observer creation. - po.observe({type: 'largest-contentful-paint', buffered: true}); - -} catch (e) { - // Do nothing if the browser doesn't support this API. -} +```js +const observer = new PerformanceObserver((list) => { + const entries = list.getEntries(); + const lastEntry = entries[entries.length - 1]; // Use the latest LCP candidate + console.log(lastEntry.url); +}); +observer.observe({ type: "largest-contentful-paint", buffered: true }); ``` ## Specifications diff --git a/files/jsondata/GroupData.json b/files/jsondata/GroupData.json index 5aa2064f6a5eb78..e386f77b654d926 100644 --- a/files/jsondata/GroupData.json +++ b/files/jsondata/GroupData.json @@ -935,8 +935,7 @@ "/docs/Web/API/Resource_Timing_API/Using_the_Resource_Timing_API", "/docs/Web/API/User_timing_API", "/docs/Web/API/User_timing_API/Using_the_User_Timing_API", - "/docs/Web/API/Element_timing_API", - "/docs/Web/API/Largest_Contentful_Paint_API" + "/docs/Web/API/Element_timing_API" ], "interfaces": [ "EventCounts",