Core Web Vitals
Core Web Vitals er Googles officielle metrics for at måle brugeroplevelse på webben. De er en vigtig ranking faktor og påvirker direkte din SEO performance.
Hvad er Core Web Vitals?
Core Web Vitals er tre nøglemetrics der måler forskellige aspekter af brugeroplevelsen:
LCP
Largest Contentful Paint
Måler indlæsningshastighed - hvor lang tid det tager før hovedindholdet vises
INP
Interaction to Next Paint
Måler interaktivitet - hvor hurtigt siden reagerer på brugerinteraktioner
CLS
Cumulative Layout Shift
Måler visuel stabilitet - hvor meget indhold flytter sig under indlæsning
LCP - Largest Contentful Paint
Hvad tæller som LCP?
LCP er det største synlige element i viewport når siden loader:
- •
<img>
elementer - •
<image>
elementer i SVG - •
<video>
poster billeder - • Baggrundsbilleder loadet via CSS
url()
- • Block-level elementer med tekst
Hvordan Optimerer Man LCP?
1. Optimer billeder
- • Brug moderne formater (WebP, AVIF)
- • Komprimer billeder uden synligt kvalitetstab
- • Brug korrekt billedestørrelse (ikke større end nødvendigt)
- • Implementer lazy loading for billeder under fold
- • Preload LCP billede
2. Reducer server response tid
- • Brug CDN for statiske assets
- • Optimer database queries
- • Implementer server-side caching
- • Brug HTTP/2 eller HTTP/3
- • Overføj Edge/Vercel for global performance
3. Minimer render-blocking resources
- • Inline kritisk CSS
- • Defer ikke-kritisk CSS og JavaScript
- • Minify CSS og JavaScript
- • Fjern ubrugt CSS
- • Use
async
ellerdefer
på scripts
// Next.js Image Optimization for LCP
import Image from 'next/image' export default function Hero() { return ( <Image src="/hero.jpg" alt="Hero image" width={1200} height={600} priority // Preload LCP image! quality={85} placeholder="blur" blurDataURL="data:image/..." /> ) }
INP - Interaction to Next Paint
Hvad måler INP?
INP måler tiden fra en bruger interagerer med siden (klik, tap, keyboard input) til næste frame vises. Det erstattede FID (First Input Delay) i marts 2024.
INP ser på ALLE interaktioner under hele besøget og vælger den værste (95. percentil).
Hvordan Optimerer Man INP?
1. Reducer JavaScript execution time
- • Opdel lange tasks (>50ms) i mindre chunks
- • Brug
requestIdleCallback
for non-critical work - • Implement code splitting
- • Minify og tree-shake JavaScript
- • Undgå tunge third-party scripts
2. Optimer event handlers
- • Debounce/throttle scroll og resize handlers
- • Brug passive event listeners
- • Undgå synchronous layout calculations (forced reflows)
- • Batch DOM updates
3. Reducer main thread work
- • Flyt tung processing til Web Workers
- • Brug
React.memo
til at undgå unødvendige re-renders - • Virtualiser lange lister (react-window, react-virtualized)
- • Lazy load components under fold
// Debounce eksempel for bedre INP
function debounce(func: Function, wait: number) { let timeout: NodeJS.Timeout return function executedFunction(...args: any[]) { clearTimeout(timeout) timeout = setTimeout(() => func(...args), wait) } } // Brug i React const handleSearch = debounce((query: string) => { // Tung søgeoperation performSearch(query) }, 300) <input onChange={(e) => handleSearch(e.target.value)} />
CLS - Cumulative Layout Shift
Hvad forårsager Layout Shifts?
CLS sker når synligt indhold flytter sig uventet. Typiske årsager:
- • Billeder uden width/height attributter
- • Annoncer, embeds og iframes uden reserved space
- • Dynamisk indhold der indsættes over eksisterende indhold
- • Web fonts der loader med FOIT/FOUT
- • Animations der ikke bruger transform/opacity
Hvordan Optimerer Man CLS?
1. Sæt eksplicitte dimensioner på billeder
<!-- ❌ Dårligt - forårsager layout shift --> <img src="image.jpg" alt="Description"> <!-- ✅ Godt - reserverer plads --> <img src="image.jpg" alt="Description" width="800" height="600" > <!-- ✅ Next.js Image (automatisk aspect ratio) --> <Image src="/image.jpg" alt="Description" width={800} height={600} />
2. Reserver plads til dynamisk indhold
/* Reserver plads til annoncer */ .ad-container { min-height: 250px; /* Annoncens forventede højde */ background: #f0f0f0; } /* Skeleton loader for async indhold */ .skeleton { height: 200px; background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); animation: shimmer 1.5s infinite; }
3. Optimer font loading
/* font-display strategier */ @font-face { font-family: 'CustomFont'; src: url('/fonts/custom.woff2') format('woff2'); font-display: swap; /* Vis fallback først, swap når loaded */ /* Alternativer: */ /* font-display: optional; */ /* Brug kun hvis loaded hurtigt */ /* font-display: fallback; */ /* Swap kun i kort periode */ } /* Preload kritiske fonts */ <link rel="preload" href="/fonts/custom.woff2" as="font" type="font/woff2" crossOrigin="anonymous" />
4. Undgå at indsætte indhold over eksisterende
- • Brug
transform
for animations i stedet fortop/left
- • Indsæt banners/notifikationer under indhold, ikke over
- • Brug
position: sticky
forsigtigt - • Test med slow 3G connection i DevTools
Værktøjer til Måling
PageSpeed Insights
Googles officielle tool med både lab og field data for Core Web Vitals
pagespeed.web.dev →Google Search Console
Core Web Vitals rapport med real user data fra Chrome brugere
search.google.com/search-console →Chrome DevTools
Lighthouse audit og Performance panel for detaljeret analyse
Web Vitals Extension
Chrome extension der viser Core Web Vitals real-time mens du browser
Chrome Web Store →Vercel Analytics
Real user monitoring med Core Web Vitals tracking for Next.js apps
vercel.com/analytics →Next.js Performance Tips
1. Brug Next.js Image Component
Automatisk optimization, lazy loading og moderne formater
import Image from 'next/image' // Automatisk WebP/AVIF, lazy loading, blur placeholder <Image src="/photo.jpg" alt="Description" width={800} height={600} quality={85} priority // For LCP billeder />
2. Implementer Dynamic Imports
Code splitting for at reducere initial bundle size
import dynamic from 'next/dynamic' // Lazy load heavy components const HeavyComponent = dynamic(() => import('./HeavyComponent'), { loading: () => <p>Loading...</p>, ssr: false // Client-side only hvis nødvendigt }) // Lazy load med suspense const Chart = dynamic(() => import('./Chart'), { suspense: true })
3. Brug Font Optimization
Next.js 13+ har indbygget font optimization
import { Inter, Roboto } from 'next/font/google' // Google Fonts med automatic optimization const inter = Inter({ subsets: ['latin'], display: 'swap', variable: '--font-inter' }) // Local fonts const myFont = localFont({ src: './my-font.woff2', display: 'swap' })
4. Enable Compression
Gzip/Brotli compression for mindre bundle sizes
// next.config.js module.exports = { compress: true, // Enabled by default // Vercel/hosting kører automatisk Brotli // For custom server: experimental: { // Optimize chunks optimizeCss: true, optimizePackageImports: ['lodash', 'date-fns'] } }
Almindelige Fejl
At teste kun på hurtig forbindelse
Mange brugere er på mobil med langsom forbindelse. Test med "Slow 3G" i Chrome DevTools.
For mange third-party scripts
Hver ekstra script (analytics, ads, chat widgets) påvirker performance. Vælg med omhu.
Ikke at måle field data
Lab data (Lighthouse) er ikke nok. Brug Search Console eller RUM for real user metrics.
Glemme mobile optimization
Google bruger primært mobile metrics for ranking. Mobil performance er kritisk.
Quick Wins Checklist
Hurtige forbedringer du kan implementere i dag: