Core Web Vitals optimieren: Web-Performance Guide

Guide to optimizing Core Web Vitals (LCP, INP, CLS) with practical techniques for improving web performance

Core Web Vitals optimieren: Web-Performance Guide

Vor ein paar Wochen war ich in den PageSpeed-Logs einer Seite, die ich technisch für sauber hielt: SSR, Image-Optimization, alles ordentlich. Trotzdem 38/100 bei Mobile-Performance, INP rot, LCP gerade so im gelben Bereich. Lehre: Core Web Vitals messen Realität, nicht Konfiguration.

Die drei Metriken sind seit 2024 stabil — INP hat FID ersetzt, sonst keine großen Änderungen. Was sich geändert hat, ist der Mess-Mechanismus: CrUX (Chrome User Experience Report) liefert echte Daten echter Nutzer, nicht synthetische Lab-Werte. Das macht Optimierung manchmal frustrierend, weil Lab-Tests grün sind und Field-Daten trotzdem rot.

Was die drei Metriken eigentlich messen

LCP (Largest Contentful Paint) — wann ist das größte sichtbare Element gerendert. Meist ein Hero-Bild oder ein großer Headline-Block. Threshold: ≤ 2.5 s.

INP (Interaction to Next Paint) — wie lange braucht der Browser, um auf eine Nutzerinteraktion mit visuellem Feedback zu reagieren. Misst alle Interaktionen, nicht nur die erste. Threshold: ≤ 200 ms.

CLS (Cumulative Layout Shift) — wie stark verschiebt sich der sichtbare Content während des Ladens. Threshold: ≤ 0.1.

Was die drei verbindet: alle field-gemessen, also abhängig von Endgerät und Verbindung des echten Nutzers.

LCP optimieren

Hauptursachen für schlechtes LCP, in absteigender Häufigkeit:

  1. Bilder, die nicht priorisiert geladen werden
  2. Render-blocking JS oder CSS
  3. Server-TTFB zu hoch
  4. Web-Fonts, die FOIT/FOUT verursachen

Konkret: das LCP-Element identifizieren (PerformanceObserver oder PageSpeed Insights), dann in Reihenfolge prüfen:

  • Hat das Bild loading="eager" und fetchpriority="high"?
  • Wird ein <link rel="preload"> für kritische Assets gesetzt?
  • Ist die Komprimierung sinnvoll? AVIF oder WebP statt JPEG bei richtigen Dimensionen?

Bei meinem Portfolio hatte ich ein 200 KB Hero-Bild als WebP mit loading="lazy" (Default in Next.js bei <Image>). LCP lag bei 3.2 s. Mit priority (was eager + fetchpriority="high" setzt) ging's auf 1.4 s. Eine Zeile Code.

INP ist das neue Performance-Problem

Bis Ende 2024 war FID die Interaktions-Metrik. FID war einfach: misst die Verzögerung zwischen Klick und Beginn der Verarbeitung. INP misst Klick bis fertig gerendertes Update — also den vollen Roundtrip.

Folge: Apps mit teurem Rendering (große React-Komponenten-Trees, schwere State-Updates) sehen plötzlich schlecht aus, obwohl Lab-Tests das nicht zeigten.

Optimierungs-Hebel:

  • Heavy Updates batchen (startTransition in React)
  • Lange Tasks aufteilen (scheduler.yield() in modernen Browsern)
  • Re-Renders reduzieren — Memoization gezielt, nicht überall
  • Synchrone JS-Arbeit aus Event-Handlern verbannen

Bei mir hat am meisten geholfen: die Suche verzögert (useDeferredValue) und die Filterlogik in einen Web Worker ausgelagert. INP von 280 ms auf 95 ms.

CLS — Reservierung ist alles

CLS-Probleme entstehen fast immer dadurch, dass Elemente in den DOM rein-poppen und vorhandenen Content verdrängen. Bilder ohne width/height, Webfonts, die nach dem ersten Render nochmal alles neu layouten, dynamische Banner.

Das beste Mittel: Platz reservieren, bevor der Inhalt da ist.

<img src="hero.webp" width="1200" height="600" alt="...">

Das Browser-Layout reserviert anhand des Aspekt-Ratios den Platz. Bei Webfonts: font-display: swap plus passendes Fallback mit size-adjust, damit das Layout beim Font-Wechsel nicht springt.

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
  font-display: swap;
  size-adjust: 95%;
}

Brotli und Caching helfen, aber nicht so viel wie man denkt

Es ist verlockend, Performance-Probleme über Komprimierung lösen zu wollen. Brotli statt Gzip, lange Cache-Header, alles richtig — und LCP geht trotzdem nicht runter, weil das Hero-Bild beim ersten Aufruf nicht im Cache ist.

Der erste Besuch (cold cache) ist die Realität für viele Nutzer. Optimierung muss dort ansetzen, nicht beim warm-cache-Request, der ohnehin schnell ist.

Was ich heute anders mache

Weniger JS shippen, mehr SSR. Weniger CSS-in-JS, mehr static CSS. Bilder explizit dimensionieren, immer. Und vor allem: Field-Daten anschauen, nicht Lab-Tests. PageSpeed Insights zeigt sowohl als auch — der Unterschied zwischen den beiden ist oft das eigentliche Problem.