Zurück zum Blog

Core Web Vitals für animierte Websites: LCP, INP und CLS bestehen

Core Web Vitals für animierte Websites: LCP, INP und CLS bestehen

6. Oktober 2026 — Performance

Veröffentlicht

6. Oktober 2026

Lesezeit

4 Min. Lesezeit

Kategorie

Performance

Schlagwörter

  • Core Web Vitals
  • Performance
  • Animation
  • WebGL
  • LCP
  • INP
  • CLS

(Intro)Wie eine Website Scrollanimationen, WebGL und Video behält und trotzdem die Core Web Vitals besteht. Die konkreten Ursachen für schlechte LCP-, INP- und CLS-Werte – und die Lösungen.

Animierte Websites gelten als langsam, und oft zu Recht. Bewegung und gute Core Web Vitals schließen sich aber nicht aus. Die meisten Probleme haben eine Handvoll Ursachen, und für jede gibt es eine Lösung, bei der die Animation bleibt.

Diese Website hat einen Video-Hero, eine Projektwand in WebGL, WebGL-Typografie und scrollgesteuerte Animationen überall. Das sind die Regeln, auf denen sie aufgebaut ist.

Die drei Metriken in Kürze

Metrik Misst Gut
LCP — Largest Contentful Paint Wann der Hauptinhalt erscheint ≤ 2,5 s
INP — Interaction to Next Paint Wie schnell die Seite auf Tippen und Klicken reagiert ≤ 200 ms
CLS — Cumulative Layout Shift Wie stark das Layout springt ≤ 0,1

Google bewertet sie am 75. Perzentil echter Chrome-Nutzer (die Felddaten in PageSpeed Insights und der Search Console), nicht an einem Lighthouse-Lauf auf Ihrem Laptop. Testen Sie auf einem Android-Smartphone der Mittelklasse mit gedrosselter Verbindung; das kommt Ihrem 75. Perzentil näher als ein MacBook.

LCP: früh etwas Echtes zeigen

Den Hero nicht hinter einer Einblendung verstecken

Der häufigste LCP-Killer auf animierten Websites ist ein Hero, der mit opacity: 0 startet und erst nach dem Laden des JavaScripts eingeblendet wird. Der Browser kann ihn erst als gezeichnet werten, wenn er sichtbar ist – also wartet LCP auf Ihr Bundle und dann auf die Animation.

Lösung: Rendern Sie den Endzustand des Heros in HTML und CSS. Blenden Sie Nebenelemente ein, oder animieren Sie aus einem bereits sichtbaren Zustand (eine leichte Skalierung oder Verschiebung, nicht aus null Deckkraft).

Dem LCP-Element ein Posterbild und Priorität geben

Ist der Hero ein Video oder ein WebGL-Canvas, ist der LCP-Kandidat meist dessen Posterbild. Machen Sie dieses Bild klein, laden Sie es vor und geben Sie ihm hohe Priorität:

html
<link rel="preload" as="image" href="/hero/poster.avif" fetchpriority="high" />
<img src="/hero/poster.avif" alt="" fetchpriority="high" width="1600" height="900" />

Starten Sie das Video oder die WebGL-Szene erst, nachdem das Poster gezeichnet ist, und blenden Sie weich hinüber.

Schwere Bibliotheken erst bei Bedarf laden

Three.js, GSAP-Plugins und Lottie müssen nicht ins erste Bundle, wenn sie Abschnitte weiter unten antreiben. Importieren Sie sie dynamisch, sobald sich der Abschnitt dem Viewport nähert:

ts
const observer = new IntersectionObserver(async ([entry]) => {
  if (!entry.isIntersecting) return
  observer.disconnect()
  const { initScene } = await import('./scene')
  initScene(canvas)
}, { rootMargin: '400px 0px' })
observer.observe(section)

In Next.js erledigt next/dynamic mit ssr: false dasselbe für ganze Komponenten.

Medien in passender Größe ausliefern

Eine 1440p-Videoschleife auf dem Smartphone ist verschwendete Bandbreite, die mit Ihrem LCP-Bild konkurriert. Wählen Sie Quellen nach Viewport-Breite und Verbindung, und halten Sie Hero-Schleifen kurz (6–10 Sekunden, ohne Tonspur).

INP: den Main Thread frei halten

INP misst die Verzögerung zwischen einer Interaktion und dem nächsten Frame. Animation schadet hier, wenn JavaScript in jedem Frame beschäftigt ist.

Nur transform und opacity animieren

Sie werden vom Compositor verarbeitet und lösen kein Layout aus. Wer top, left, width, height oder margin animiert, erzwingt in jedem Frame ein Layout:

css
/* Slow: layout every frame */
.card { transition: top 0.3s; }

/* Fast: compositor only */
.card { transition: transform 0.3s; }

Kein Layout in Scroll-Handlern lesen

getBoundingClientRect() nach einer Stiländerung erzwingt ein synchrones Layout. Lesen Sie in Scroll-Handlern einmal pro Frame innerhalb von requestAnimationFrame und schreiben Sie danach:

ts
let ticking = false
window.addEventListener('scroll', () => {
  if (ticking) return
  ticking = true
  requestAnimationFrame(() => {
    const top = section.getBoundingClientRect().top   // read
    progressBar.style.transform = `scaleX(${clamp(-top / range)})` // write
    ticking = false
  })
}, { passive: true })

Noch besser: Lassen Sie eine Bibliothek wie ScrollTrigger von GSAP das bündeln, oder nutzen Sie CSS-Scroll-Animationen (animation-timeline: scroll()), wo sie unterstützt werden.

Arbeit stoppen, die niemand sieht

Jede requestAnimationFrame-Schleife auf der Seite läuft auf dem Main Thread. Pausieren Sie Canvas-Elemente, Videos und Schleifen, wenn sie den Viewport verlassen und wenn der Tab im Hintergrund ist:

ts
const io = new IntersectionObserver(([e]) => (e.isIntersecting ? start() : stop()))
io.observe(canvas)
document.addEventListener('visibilitychange', () => (document.hidden ? stop() : start()))

Die Canvas-Auflösung deckeln

Ein WebGL-Canvas mit devicePixelRatio 3 auf dem Smartphone rendert neunmal so viele Pixel wie bei DPR 1. Deckeln Sie den Wert:

ts
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))

Bei bildschirmfüllenden Effekten wie Nebel oder Rauschen ist halbe Auflösung mit anschließender Hochskalierung oft nicht zu unterscheiden.

Lange Tasks aufteilen

Eine Szene aufbauen, ein großes JSON parsen oder viele Text-Meshes vorbereiten kann den Thread Hunderte Millisekunden blockieren. Teilen Sie die Arbeit auf und geben Sie zwischen den Stücken die Kontrolle ab (await scheduler.yield(), wo verfügbar, sonst setTimeout(0)), damit ein Tippen während des Aufbaus schnell beantwortet wird.

CLS: für alles Platz reservieren

Medien Abmessungen geben

Jedes Bild, Video, iframe und Canvas braucht width/height-Attribute oder ein CSS-aspect-ratio, damit der Browser den Platz reserviert, bevor es lädt.

Schriften ohne Sprung laden

Display-Schriften gehören zum Charakter einer animierten Website, und ein später Schriftwechsel verschiebt jede Zeile. Laden Sie die ein, zwei kritischen Dateien vor, reduzieren Sie sie auf die nötigen Zeichen und nutzen Sie font-display: swap mit einer Fallback-Schrift mit angepassten Metriken (size-adjust, ascent-override) – next/font erzeugt das automatisch.

Animationen zählen nicht – Layoutänderungen schon

CLS ignoriert transform-Animationen, nicht aber Größen- oder Positionsänderungen über Layout-Eigenschaften. Ein Banner, das nach dem Laden Inhalte nach unten schiebt, zählt; dasselbe Banner, das mit transform in reservierten Platz gleitet, nicht.

Reduzierte Bewegung respektieren

Manche Besucher stellen in ihrem Betriebssystem weniger Bewegung ein. Respektieren Sie das – es ist eine Anforderung der Barrierefreiheit, und diese Besucher bekommen zudem eine leichtere Seite:

css
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

Prüfen Sie in JavaScript matchMedia('(prefers-reduced-motion: reduce)'), bevor Sie Schleifen, Parallax-Effekte und automatisch startende Videos starten.

Ein Workflow, der Rückschritte erkennt

  1. Zeichnen Sie in den Chrome DevTools einen Performance-Trace mit 4-facher CPU-Drosselung auf, während Sie durch die ganze Seite scrollen. Achten Sie auf lange Tasks und lila Layout-Balken.
  2. Schalten Sie Rendering → Paint flashing und Layout Shift Regions ein, um zu sehen, was neu gezeichnet wird und sich verschiebt.
  3. Prüfen Sie nach dem Launch wöchentlich die Felddaten in PageSpeed Insights; Laborwerte sind eine Orientierung, Felddaten sind die Note.

Checkliste

  • Hero-Inhalt im initialen HTML sichtbar, nicht aus null eingeblendet
  • LCP-Bild mit fetchpriority="high" vorgeladen
  • Schwere Bibliotheken bei Bedarf geladen
  • Nur transform und opacity animiert
  • Layout-Lesezugriffe in requestAnimationFrame gebündelt
  • Schleifen, Canvas-Elemente und Videos außerhalb des Bildschirms pausiert
  • Pixel Ratio des Canvas gedeckelt
  • Abmessungen für alle Medien; Schriften mit metrisch angepassten Fallbacks
  • prefers-reduced-motion respektiert

Zur Animationsseite des Themas siehe GSAP in React und Next.js.

Newsletter

Neue Beiträge per E-Mail

Eine kurze E-Mail, wenn es etwas Neues gibt. Kein Spam, jederzeit abbestellbar.

GSAP in React und Next.js: useGSAP, Cleanup und ScrollTrigger
GSAP in React und Next.js: useGSAP, Cleanup und ScrollTrigger
Nächster Beitrag