# Core Web Vitals

## Hva det er

Dokumentasjonen til Google på web.dev plukker ut tre måltall fra det bredere Web Vitals-programmet
og kaller dem kjernen: Largest Contentful Paint for lasting, Interaction to Next Paint for
responsivitet og Cumulative Layout Shift for visuell stabilitet. Hvert av dem beskriver noe en
besøkende merker, gjelder for hver side og kan måles i felt, i nettleserne til ekte besøkende.

Largest Contentful Paint (LCP) er tiden fra navigasjonen starter til det største bildet, den
største tekstblokken eller videoen som er synlig i visningsområdet, er tegnet opp. Den er god ved
2,5 sekunder eller mindre og dårlig over 4 sekunder.

Interaction to Next Paint (INP) følger hvert klikk, trykk og tastetrykk under et besøk og tar med
hele ventetiden den besøkende ser: forsinkelsen før hendelseshåndtererne starter, tiden de kjører,
og tiden til neste bilde er tegnet. Sidens INP er den tregeste av disse, med én avvikende verdi
fjernet per 50 interaksjoner. Rulling, å holde pekeren over noe og zooming holdes utenfor. Den er
god ved 200 millisekunder eller mindre og dårlig over 500. INP erstattet First Input Delay
den 12. mars 2024, etter å ha blitt introdusert som et eksperimentelt måltall i mai 2022. First
Input Delay målte bare forsinkelsen før hendelseshåndtererne for den første interaksjonen startet.

Cumulative Layout Shift (CLS) gir poeng til synlige elementer som flytter seg uten at noen har bedt
om det. Hvert skift får en verdi som er andelen av visningsområdet de flyttede elementene dekker,
ganget med hvor langt de flytter seg. Skift som kommer mindre enn ett sekund etter hverandre,
opptil fem sekunder til sammen, danner et øktvindu (_session window_), og CLS er summen for det
verste vinduet. Skift innen 500 millisekunder etter et trykk, et klikk eller et tastetrykk blir
unnskyldt, mens rulling og dra-bevegelser unnskylder ingenting. Den er god ved 0,1 eller mindre og
dårlig over 0,25.

Vurderingen leses ved 75. persentil av sidelastingene, hver for seg for mobil og datamaskin, og en
side består bare når alle tre er gode der. En grense for «god» ble bare godtatt hvis minst en tidel
av opphavene (_origins_) allerede nådde den.

Under ligger nettlesergrensesnitt med egne spesifikasjoner, API-ene Largest Contentful Paint,
Layout Instability og Event Timing, og noen få linjer viser råmaterialet til CLS på hvilken som
helst side:

```js
new PerformanceObserver((list) => {
    for (const shift of list.getEntries()) {
        if (!shift.hadRecentInput) console.log(shift.value, shift.sources);
    }
}).observe({ type: "layout-shift", buffered: true });
```

Det logger enkeltskift, og ikke selve måltallet. For de tre slik verktøyene til Google rapporterer
dem, viser web.dev til biblioteket `web-vitals`.

Begrepet er lett å forveksle med ytelsespoengsummen i Lighthouse, som kommer fra én simulert
lasting i et laboratorium, uten en eneste besøkende i den. Vurderingen av Core Web Vitals beskriver
ekte besøk ved 75. persentil, og en side kan gjøre det godt på den ene og dårlig på den andre.

## Hvorfor det er viktig

Definisjonene lar det stå åpent hvor tallene kommer fra, og det er den beslutningen et nettsted må
ta: styre etter erstatningsmål fra laboratoriet, eller betale for feltdata.

Feltdata er det tersklene er skrevet for.
[Chrome User Experience Report](https://developer.chrome.com/docs/crux) (CrUX) samler anonymiserte
målinger fra ekte besøkende som bruker Chrome, og forsyner PageSpeed Insights og rapporten om Core
Web Vitals i Search Console uten at nettstedet legger til noe, men først når en side eller et
opphav har nok besøkende. Alternativet er et skript i nettleseren til den besøkende som sender hver
måling til en server: en beslutning om personvern, og en kostnad som bæres ved hver sidevisning.

Laboratoriedata koster ingen av delene. Lighthouse laster siden på en simulert enhet og et simulert
nettverk, før en endring sendes ut og så ofte du vil. Det den måler, er et besøk som aldri fant
sted. Den ser LCP og CLS under lastingen, men siden det ikke er noen som trykker på noe, har den
heller ingen INP. web.dev tilbyr Total Blocking Time som erstatningsmål i laboratoriet og sier at
det ikke er en fullverdig erstatning.

Den delingen som fungerer, er begge deler, holdt fra hverandre: laboratorietall som budsjetter som
fanger en endring til det verre, og felttall, der de finnes, som den eneste dommen over det de
besøkende faktisk får.

## Slik ser det ut i praksis

Et planleggingsnotat viser at en jobb for Core Web Vitals ble vurdert og valgt bort: Chrome UX
Report krever en API-nøkkel og nok trafikk til å rapportere, og sidene holdes allerede til
størrelsesbudsjetter i kvalitetsporten. Nettstedet samler heller ikke inn noe selv. Kolofonen sier
at det [kjører ett skript, på omtrent en kilobyte, og ingen analyse](/nb/credits/), og det
skriptet, listefilteret, er det eneste som kunne holdt igjen et klikk eller et tastetrykk. Den
samme siden viser leserne til PageSpeed Insights, som viser målinger fra ekte besøk når en side har
nok av dem.

Det nettstedet måler i stedet, er laboratoriet. Lighthouse-konfigurasjonen laster en fast liste med
sider tre ganger hver under simulert struping for mobil og melder feil når en av de engelske eller
danske sidene krysser en av disse grensene: LCP over 4 200 millisekunder, First Contentful Paint
over 1 600, CLS over 0,02 og Total Blocking Time over 100, med litt romsligere grenser for
opptegning på de ukrainske sidene. Dette er budsjetter og ikke terskelverdiene for felt, og de ble
skrevet etter at variasjonen fra kjøring til kjøring var målt til 299 millisekunder i verste fall
og 80 i beste, fordi en grense innenfor det spennet består eller feiler tilfeldig. Prosjektnotatene
fører mesteparten av LCP-tiden tilbake til ventetid på opptegning bak ett enkelt stilark som
blokkerer opptegningen. Vekt som kommer før noe innhold, var allerede kuttet:
[stilarkpakken veide 87 KB med en base64-kodet skrift inni og 31 uten](/nb/portfolio/cut-the-stylesheet-bundle-from-87kb-to-31kb-139/).
Kjøringene tar minutter, så de skjer ved behov, utenfor kvalitetsporten.

CLS-budsjettet, fem ganger strengere enn grensen på 0,1, fanget et tilfelle som er verdt å ta vare
på. En kategoriside feilet med 0,107. Eieren åpnet den, så ingenting galt og sa fra om det.
Lighthouse hadde pekt ut parallakse-tannhjulene som synderen, og den første skriftlige diagnosen
trodde på det. En kontrollert test med en ekte bevegelse på musehjulet ga 0,2477 enten
tannhjulene beveget seg eller ikke, mens overskriften og det siste avsnittet flyttet seg null
piksler hele veien. Årsaken var bunnteksten: den er festet til visningsområdet og endrer høyde når
kolofonen i den åpnes, og måltallet gir den boksen poeng mot visningsområdet selv om et fast
element ikke kan skyve noe. Budsjettet ble stående der det var. Hvis tallet en gang skal dempes, er
planen et unntak for den ene adressen.

## Hvor det går galt

**En laboratorierapport utelater INP, og siden antas å svare raskt.** Lighthouse viser LCP og CLS,
Total Blocking Time er lav, og trege klikk i produksjon kommer som en overraskelse. En simulert
lasting har ingen som samhandler med siden, og Total Blocking Time teller bare blokkering av
hovedtråden under den lastingen. Les tallet som et varsellys, mål ekte interaksjoner for hånd i
ytelsesverktøyene i nettleseren, og bedøm INP ut fra feltdata der det finnes noen.

**Elementet et verktøy gir skylden, viser seg å være uskyldig.** Rapporten navngir en node for et
layoutskift, en endring av den noden flytter poengsummen ingenting, og teksten på skjermen ligger
i ro. Attribusjonen navngir noder, og ikke årsaker. Skiftet kan høre til et fast overlegg som
endrer høyde, noe som teller som bevegelse og som rulling ikke unnskylder. Slå av de mistenkte én
om gangen, mål om innholdet flytter seg, og animer størrelse med `transform`, som web.dev anbefaler
fordi det ikke gir noe layoutskift.

**Innholdet hopper nedover mens bilder og sene elementer lastes.** Leserne mister plassen sin, og
CLS i felt klatrer over 0,1. web.dev lister de vanlige årsakene: bilder og video av ukjent
størrelse, webfonter som tegnes større eller mindre enn reservefonten, og widgeter som endrer
størrelse selv. Gi hvert bilde attributtene `width` og `height`, så nettleseren setter av plass til
boksen, slik bildepartialene på dette nettstedet gjør, og sett av plass til alt som settes inn
senere.

**Et sunt gjennomsnitt skjuler en vurdering som stryker.** Et dashbord viser en gjennomsnittlig LCP
godt under 2,5 sekunder, og likevel er siden vurdert til å trenge forbedring. Vurderingen
bruker 75. persentil, per enhetsklasse, og en treg fjerdedel av mobilbesøkene forsvinner i et
gjennomsnitt som tar med raske datamaskiner. Rapporter og sett mål ved 75. persentil, delt etter
enhet.

## Les mer

- [Web Vitals](https://web.dev/articles/vitals) — de tre måltallene, tersklene deres og verktøyene
  som rapporterer dem.
- [Defining the Core Web Vitals metrics thresholds](https://web.dev/articles/defining-core-web-vitals-thresholds)
  — hvorfor 75. persentil, og hvordan hver grense ble testet.
- [Interaction to Next Paint](https://web.dev/articles/inp) — hva som regnes som en interaksjon, og
  hvordan INP skiller seg fra First Input Delay.
- [Largest Contentful Paint API](https://wicg.github.io/largest-contentful-paint/) — hvilke
  elementer som er kandidater, og når tiden deres tas.
- [Layout Instability API](https://wicg.github.io/layout-instability/) — poengsummen for
  layoutskift, nylig input og kildene til hvert skift.
- [Event Timing API](https://w3c.github.io/event-timing/) — hvordan forsinkelsen i interaksjoner
  gjøres tilgjengelig for skript.

<https://engineer.company/nb/glossary/core-web-vitals/>
