Slide 1

Slide 1 text

Core Web Vitals and their effect on User Experience What makes your site feel snappy?

Slide 2

Slide 2 text

Abbé Jean-Antoine Nollet 1700 - 1770 French Clergyman & Budding Electrician Invented one of the first Electroscopes (we now call them beacon collectors) L'Abbé Jean Antoine Nollet — Maurice Quentin de La Tour Alte Pinakothek, Munich, Germany Public Domain

Slide 3

Slide 3 text

In 1746, he conducted the first ever RUM Experiment

Slide 4

Slide 4 text

Philip Tellis Principal RUM Distiller @ Akamai ● Creator of mPulse and tinkerer of the data ● Author of the OpenSource boomerang RUM library social:@bluesmoon ⦿ github:@bluesmoon speakerdeck:@bluesmoon

Slide 5

Slide 5 text

Core Web VitaLs ★ Largest Contentful Paint ★ Cumulative Layout Shift ★ Interaction to Next Paint

Slide 6

Slide 6 text

https://addyosmani.com/blog/usability/ LOADING A WEBPAGE LCP keeps updating

Slide 7

Slide 7 text

LCP keeps updating 0.3% WHEN DO USERS INTERACT WITH A SITE? 9% 57%

Slide 8

Slide 8 text

Largest Contentful Paint (LCP) When did the biggest thing show up on screen?

Slide 9

Slide 9 text

LCP reports the render time of the largest image, text block, or video visible in the viewport. https://web.dev/articles/lcp

Slide 10

Slide 10 text

★ Render time ★ Foreground or background Images including inline ★ “Largest” is related to rendered screen size ★ Text nodes ★ Only rendered portions after clipping ★ Not related to download time ★ No CSS gradient backgrounds ★ No placeholders or low entropy images ★ Nothing invisible ★ Text nodes using Web Fonts during the Font block period What does this include / exclude?

Slide 11

Slide 11 text

LCP reporting stops when the user interacts

Slide 12

Slide 12 text

new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { // element, id, url, // renderTime, loadTime, size } }).observe({ type: "largest-contentful-paint", buffered: true }); performance.getEntriesByType("largest-contentful-paint") is deprecated!

Slide 13

Slide 13 text

Object Structure ● element: A reference to the DOM element that was painted ● id: The id attribute of the element ● url: The Url for images. This might also be a data uri. ● renderTime: The relative timestamp when the object was rendered, 0 for cross-origin objects without T-A-O. ● loadTime: The relative timestamp when the object was loaded. ● size: The number of square pixels rendered (height x width) https://developer.mozilla.org/en-US/docs/Web/API/LargestContentfulPaint

Slide 14

Slide 14 text

< 2.5s Google suggests keeping the value under 2.5s at the 75th percentile (that’s about as long as a yawn)

Slide 15

Slide 15 text

Split elements by Category

Slide 16

Slide 16 text

Scale thresholds for different percentiles

Slide 17

Slide 17 text

% of screen covered, render/load time, correlation with other timers

Slide 18

Slide 18 text

Overlay the timer on an aggregate waterfall.

Slide 19

Slide 19 text

Cumulative Layout Shift (CLS) How much did things move during load?

Slide 20

Slide 20 text

CLS is a measure of the largest burst of layout shift scores for every unexpected layout shift that occurs during the entire lifecycle of a page. https://web.dev/articles/cls Layout Shift is a fractional value between 0 and 1

Slide 21

Slide 21 text

Layout Shift = Impact Fraction * Distance Fraction https://nicj.net/cumulative-layout-shift-in-practice/

Slide 22

Slide 22 text

https://nicj.net/cumulative-layout-shift-in-practice/

Slide 23

Slide 23 text

https://nicj.net/cumulative-layout-shift-in-practice/

Slide 24

Slide 24 text

Layout Shift = 0.5 * 0.2 = 0.1 https://nicj.net/cumulative-layout-shift-in-practice/

Slide 25

Slide 25 text

new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { // sources, // value, // hadRecentInput, // lastInputTime, // startTime } }).observe({type: "layout-shift",buffered: true});

Slide 26

Slide 26 text

Object Structure ● sources: A list of Layout Shift Attributions: ○ node: The node that shifted; Null if no longer in the DOM ○ previousRect, currentRect ● startTime: Relative timestamp when the layout shift started. ● value: The layout shift value. ● lastInputTime: Relative timestamp of the most recent excluding input. ● hadRecentInput: true if the above was less than 500ms https://developer.mozilla.org/en-US/docs/Web/API/LayoutShift

Slide 27

Slide 27 text

< 0.1 Google suggests keeping the value under 0.1 at the 75th percentile

Slide 28

Slide 28 text

Look at LoAF* entries & Resource Downloads that happen at the time of a layout shift.

Slide 29

Slide 29 text

CLS reporting never stops!

Slide 30

Slide 30 text

Interaction to Next Paint (INP) How long did the user have to wait after doing something on the page?

Slide 31

Slide 31 text

INP is a measure of the page’s overall responsiveness to user interactions. https://web.dev/articles/inp INP is the (approx) longest observed interaction latency so far.

Slide 32

Slide 32 text

new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { // target (null if removed), // duration, // startTime, // processingStart, // processingEnd } }).observe({ type: "event", buffered: true, durationThreshold: 16 }); https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEventTiming

Slide 33

Slide 33 text

< 200ms Google suggests keeping the value under 200ms at the 75th percentile (blink of an eye is 300ms)

Slide 34

Slide 34 text

★ Includes a start time & duration ★ Can collect this value incrementally to identify all INP durations on the page ★ You need to maintain your own interaction buffer. ★ Remember to reset the buffer for multiple transitions in a SPA. ★ Not all pages have an interaction. ★ Disable your listener if the page is not visible Notes…

Slide 35

Slide 35 text

LoAF* / Resources / Errors that overlap INP start → end might be interesting.

Slide 36

Slide 36 text

Mais Pourquoi?

Slide 37

Slide 37 text

It’s not ^ SEO! just

Slide 38

Slide 38 text

LCP is negatively correlated with retention rate ρ=-0.80

Slide 39

Slide 39 text

CLS is strongly correlated with reload rate ρ=0.84

Slide 40

Slide 40 text

INP is strongly correlated with rage clicking ρ=0.83

Slide 41

Slide 41 text

Et Tout Ensemble?

Slide 42

Slide 42 text

A fast LCP is a signal to the user that the page is ready for Interactions % of users who interact

Slide 43

Slide 43 text

A fast LCP is a signal to the user that the page is ready for Interactions INP value for those interactions

Slide 44

Slide 44 text

A fast LCP is a signal to the user that the page is ready for Interactions Rage clicks for users that interacted at this time

Slide 45

Slide 45 text

A fast LCP is a signal to the user that the page is ready for Interactions This is when the page looks complete

Slide 46

Slide 46 text

A fast LCP is a signal to the user that the page is ready for Interactions This is when the page is usable

Slide 47

Slide 47 text

Focus on the entire User Experience!

Slide 48

Slide 48 text

Happier users stick around longer!

Slide 49

Slide 49 text

Thank You!