[eventloop.de / frontend] Hauptseite v2026.06.0

Eventloop

Magazin für JavaScript, Frontend und Web-APIs

← Magazin 01. Juni 2026
Performance · 12 min

Core Web Vitals 2026 — INP statt FID und LCP-Optimierung

INP hat FID seit März 2024 als Core Web Vital ersetzt. Was die neue Metrik misst, wie LCP optimiert wird und welche Tools 2026 für Real-User-Monitoring relevant sind.

Im März 2024 hat Google die Core Web Vitals umgestellt: FID (First Input Delay) ist abgelöst, INP (Interaction to Next Paint) ist der neue Reaktionszeit-Indikator. Die Umstellung ist mehr als eine Umbenennung — INP misst grundsätzlich anders und legt damit Performance-Probleme offen, die FID jahrelang verdeckt hat.

Warum INP und nicht FID

FID hat ausschließlich die Verzögerung zwischen der ersten Nutzer-Interaktion und dem Beginn der Event-Handler-Ausführung gemessen. Das ließ zwei wesentliche Aspekte aus: alle Interaktionen nach der ersten, und die Zeit zwischen Handler-Ende und tatsächlichem visuellen Update. In der Praxis war FID ein zu optimistischer Indikator — eine Seite konnte 50 ms FID erreichen und sich trotzdem nach dem ersten Klick zäh anfühlen, weil jede weitere Interaktion 500 ms blockierte.

INP misst über die gesamte Session hinweg die längste Interaktions-Latenz (mit einer Toleranz, die abhängig von der Gesamtzahl der Interaktionen kleinere Ausreißer ignoriert). Eine Interaktion umfasst: Eingangs-Event, alle ausgelösten Event-Handler, das Rendering, der Paint. Damit wird auch sichtbar, wenn ein Click-Handler zwar in 30 ms zurückkehrt, aber durch einen React-State-Update einen 400-ms-Re-Render auslöst.

INP-Schwellen

  • Good: unter 200 ms
  • Needs Improvement: 200-500 ms
  • Poor: über 500 ms

Die Schwellen gelten für das 75. Perzentil der Real-User-Daten. Eine Site, deren INP-p75 bei 180 ms liegt, gilt als „Good” — auch wenn einzelne Nutzer schlechtere Werte sehen.

LCP — der visuelle Lade-Hauptindikator

LCP (Largest Contentful Paint) misst den Zeitpunkt, zu dem das größte sichtbare Element im Viewport gerendert ist. „Größtes Element” wird heuristisch bestimmt: Bilder, Hintergrund-Bilder, Block-Text-Elemente und SVG-Inline-Grafiken werden berücksichtigt. Die Schwellen sind seit 2020 unverändert:

  • Good: unter 2,5 s
  • Needs Improvement: 2,5 - 4 s
  • Poor: über 4 s

Die größten LCP-Killer sind 2026 nach wie vor unoptimierte Bilder, blockierende CSS-Dateien und Render-blocking-JavaScript im Header. Wer LCP unter 2,5 s drückt, hat in der Regel die größte Hebelwirkung auf das Gesamt-Vital-Profil.

CLS und TTFB — die übrigen Vitals

CLS (Cumulative Layout Shift) misst, wie stark sich Elemente während des Ladens verschieben. Schwellen: Good unter 0,1, Needs Improvement 0,1-0,25, Poor über 0,25. Die häufigsten CLS-Quellen sind Web-Fonts ohne font-display: optional, Bilder ohne width- und height-Attribute, und dynamisch eingeblendete Banner.

TTFB (Time to First Byte) ist kein Core Web Vital, aber als Diagnose-Wert wichtig: Wenn TTFB bei 1,5 s liegt, kann LCP physikalisch nicht unter 2,5 s landen. Google empfiehlt TTFB unter 800 ms.

LCP-Optimierung

Bildformate

AVIF und WebP liefern bei vergleichbarer Bildqualität 30-60 Prozent kleinere Dateien als JPEG oder PNG. Eine 240-kB-JPEG-Hero wird in AVIF zu 95 kB, in WebP zu 140 kB. Browser-Support ist 2026 vollständig: AVIF wird von Chrome, Firefox, Safari (seit 16.4) und Edge unterstützt.

<picture>
  <source type="image/avif" srcset="hero.avif" />
  <source type="image/webp" srcset="hero.webp" />
  <img src="hero.jpg" width="1200" height="600" alt="…"
       fetchpriority="high" />
</picture>

Das fetchpriority-Attribut

fetchpriority="high" hebt das LCP-Bild im Browser-Priority-Scheduler auf das Niveau eines render-blocking-CSS. Ohne den Hint bekommt ein <img>-Tag im Body eine niedrige Priorität — der Browser lädt es erst, nachdem alle CSS- und JS-Ressourcen im Head geparsed sind. Mit dem Hint startet der Download parallel. Messbarer Effekt auf LCP: 200-500 ms Verbesserung auf typischen Hero-Sektionen.

Resource-Hints

<link rel="preload"> und <link rel="modulepreload"> schieben kritische Ressourcen vor den restlichen Discovery-Prozess. Sinnvoll für: Hero-Bilder (wenn nicht im initialen HTML referenziert), kritische Fonts, kritische JavaScript-Module.

<link rel="preload" href="/fonts/inter-var.woff2"
      as="font" type="font/woff2" crossorigin />
<link rel="modulepreload" href="/js/app.js" />

HTTP/2-Server-Push wurde 2022 von Chrome abgeschafft und steht in HTTP/3 nicht zur Verfügung. Wer noch Push-Konfigurationen in seinem Nginx hat, kann sie entfernen — sie haben 2026 keine Wirkung mehr.

INP-Optimierung

INP-Probleme sind fast immer JavaScript-Probleme: ein Event-Handler, der zu lange läuft, oder ein Re-Render, der den Main-Thread blockiert. Drei Strategien greifen praktisch:

scheduler.yield() — Tasks aufteilen

scheduler.yield() ist eine 2024 standardisierte API, die einen langen Task in mehrere kleinere zerlegt und dem Browser zwischendurch erlaubt, Rendering und andere Tasks zu erledigen.

async function processLargeArray(items) {
  for (const item of items) {
    process(item);
    if (navigator.scheduling?.isInputPending() ||
        performance.now() - lastYield > 50) {
      await scheduler.yield();
      lastYield = performance.now();
    }
  }
}

Die Wirkung: Eine Operation, die früher den Main-Thread für 800 ms blockiert hat, läuft mit Yields in 16-ms-Slots ab. Die Gesamtdauer steigt minimal (durch den Overhead des Yieldings), die INP fällt drastisch.

requestIdleCallback für Hintergrund-Arbeit

Für Arbeit, die nicht zeitkritisch ist (Analytics-Senden, Cache-Warming, Logging), ist requestIdleCallback das richtige Werkzeug. Der Callback läuft nur, wenn der Browser tatsächlich Leerlauf hat, und bekommt ein deadline-Objekt, das anzeigt, wie viel Zeit zur Verfügung steht.

requestIdleCallback((deadline) => {
  while (deadline.timeRemaining() > 0 && tasks.length > 0) {
    tasks.shift()();
  }
}, { timeout: 2000 });

Web-Worker für CPU-intensive Operationen

Alles, was länger als 50 ms läuft und nicht direkt UI-State berührt, gehört in einen Web-Worker: Markdown-Parsing, Bildverarbeitung, Krypto, Suche in großen Datenmengen, JSON-Parsing über 1 MB. Mit Comlink oder partytown wird der Worker-Boilerplate minimal.

Real-User-Monitoring

Die web-vitals-Library v4 ist 2026 der De-facto-Standard für RUM-Vitals-Erhebung. Sie misst INP, LCP, CLS, TTFB und FCP nach den offiziellen Google-Definitionen und liefert pro Metrik ein Objekt mit Wert, Rating und Attribution-Daten.

import { onINP, onLCP, onCLS } from 'web-vitals';

onINP(({ value, rating, attribution }) => {
  analytics.send({
    metric: 'INP',
    value,
    rating,
    eventTarget: attribution.eventTarget,
    eventType: attribution.eventType,
    loadState: attribution.loadState,
  });
});

Die Attribution-Daten zeigen exakt, welches DOM-Element die schlechte Metrik verursacht hat — bei INP also der Selector des Event-Targets und der Event-Typ. Das macht aus einer abstrakten Zahl eine Diagnose, die Entwickler in den Code zurück führen kann.

Lighthouse 12 und CrUX

Lighthouse 12 (Chrome DevTools, eingebaut seit Chrome 124) wertet die Vitals im Lab-Modus aus und liefert eine reproduzierbare Baseline. Wichtig: Lab-Werte und RUM-Werte unterscheiden sich systematisch. Lighthouse simuliert eine bestimmte Netzwerk- und CPU-Klasse, die realen Nutzer-Profile sind heterogener.

Das CrUX-Dashboard (Chrome User Experience Report) liefert aggregierte RUM-Daten für jede Domain aus der echten Chrome-Nutzerbasis. Über die CrUX-API oder das Looker-Studio-Template lassen sich p75-Werte pro Origin pro Monat abrufen. Eine Site, die in CrUX bei INP-p75 von 380 ms steht, ist im „Needs Improvement”-Bereich — die RUM-Library kann zeigen, welche Komponente die Ausreißer verursacht.

Konkrete Optimierungs-Reihenfolge

Wer von „Poor” auf „Good” will, geht in der Regel in dieser Reihenfolge vor: Erst TTFB unter 600 ms drücken (CDN, statisches Pre-Rendering, ISR), dann LCP-Bild auf AVIF mit fetchpriority="high" umstellen, dann Render-blocking-JavaScript im Head identifizieren und mit defer oder async versehen, dann INP-Hotspots in den Event-Handlern messen und mit scheduler.yield() aufteilen, schließlich CLS durch explizite Dimensionen für alle Media-Elemente eliminieren.

Die ersten drei Schritte holen typischerweise 60-80 Prozent der Verbesserung, der Rest ist Feintuning. Mit dem Setup aus web-vitals v4, Lighthouse 12 als Lab-Baseline und CrUX als RUM-Wahrheitsquelle ist die Datengrundlage 2026 so gut wie nie zuvor.


Ressort: Performance