Lazy Loading richtig einsetzen und Core Web Vitals verbessern

6. Mai 2026

Lazy Loading: Bilder laden erst, wenn sie im sichtbaren Bereich sind. Das spart Daten und verbessert das Nutzererlebnis.

Inhaltsverzeichnis

Eine Webseite kann auf dem Smartphone langsam wirken, obwohl der sichtbare Inhalt längst fertig wäre. Das Prinzip hinter lazy load verschiebt nicht benötigte Bilder, Iframes, Skripte oder Komponenten auf später und entlastet dadurch Netzwerk, Browser und Nutzer. Ich zeige, wann diese Technik wirklich hilft, wie sie in HTML sowie modernen Frameworks funktioniert und welche Ressourcen besser sofort geladen werden.

Die richtige Ladeentscheidung verbessert Tempo und Nutzererlebnis

  • Außerhalb des sichtbaren Bereichs liegende Ressourcen können verzögert geladen werden.
  • LCP-Bilder und Hero-Inhalte dürfen nicht lazy geladen werden.
  • width und height verhindern Layoutverschiebungen bei Bildern.
  • React, Vue und Next.js teilen JavaScript über dynamische Imports in kleinere Pakete.
  • DevTools und Lighthouse zeigen, ob die Maßnahme tatsächlich einen messbaren Vorteil bringt.

Angular-Symbol lädt Bilder aus der Cloud. Ein Monitor zeigt eine Webseite mit Bildern, die erst nach und nach geladen werden, was auf lazy load hindeutet.

Was beim verzögerten Laden tatsächlich passiert

Beim normalen Laden fordert der Browser viele Ressourcen an, sobald er sie im HTML, CSS oder JavaScript entdeckt. Dazu gehören oft Bilder unterhalb des ersten Bildschirmbereichs, eingebettete Videos, Karten, Chat-Widgets und große Komponenten, die erst nach einer Interaktion gebraucht werden. Das verzögerte Laden behandelt solche Inhalte als nicht kritisch für den ersten Render.

Der Browser wartet, bis ein Element in die Nähe des sichtbaren Bereichs kommt. Erst dann wird die Ressource angefordert, heruntergeladen, dekodiert und dargestellt. Scrollt jemand nie bis zum Seitenende, müssen mehrere Bilder oder ein eingebettetes Video im besten Fall gar nicht übertragen werden.

Das verkürzt die sogenannte Critical Rendering Path. Gemeint ist die Kette aus HTML, CSS, JavaScript und Medien, die der Browser für die erste sichtbare Darstellung benötigt. Ich sehe den größten Effekt deshalb nicht bei einer einzelnen kleinen Grafik, sondern bei Seiten mit vielen Bildern, externen Skripten oder umfangreichen JavaScript-Paketen.

Die Technik ersetzt allerdings keine Bildkomprimierung und kein gutes Caching. Eine schlecht optimierte Datei bleibt auch dann zu groß, wenn sie erst später geladen wird. Verzögertes Laden verschiebt die Kosten, es beseitigt sie nicht.

Bilder und Iframes richtig priorisieren

Für Bilder unterhalb des ersten Bildschirmbereichs reicht in modernen Browsern meist das native HTML-Attribut loading="lazy". Es ist einfacher, robuster und wartungsärmer als eine zusätzliche Bibliothek. Ein typisches Bild in einer Artikelseite kann so aussehen:

Moderne Architektur eines Bürogebäudes

width und height sind nicht nur kosmetische Angaben. Sie reservieren Platz, bevor das Bild eintrifft, und reduzieren dadurch den Cumulative Layout Shift, also das unerwartete Springen des Layouts. Gerade auf mobilen Geräten ist dieser Platzhalter wichtig, weil langsame Verbindungen das Nachladen deutlich sichtbarer machen.

Das wichtigste Bild der Seite ist die Ausnahme. Befindet sich ein Hero-Bild im ersten Viewport oder bildet es das Largest Contentful Paint, sollte es normalerweise sofort geladen werden. Für eine solche Ressource kann fetchpriority="high" als Hinweis dienen, während loading="lazy" an dieser Stelle die Darstellung sogar verschlechtern kann.

Arbeitsplatz in einem hellen Büro

Bei Iframes ist Zurückhaltung ebenfalls sinnvoll. Eine Karte, ein Videoplayer oder ein eingebettetes Formular unterhalb des sichtbaren Bereichs kann mit loading="lazy" warten. Für Videos nutze ich zusätzlich häufig ein Posterbild und preload="none", damit nicht schon beim Seitenaufruf ein großer Medienstream startet.

Auch alternative Bildquellen sollten berücksichtigt werden. Mit srcset und sizes erhält ein Smartphone eine kleinere Datei als ein großer Desktop-Bildschirm. Das ist oft wirkungsvoller als jede zusätzliche Ladeverzögerung, weil die übertragene Datenmenge von Anfang an sinkt.

JavaScript und Frameworks gezielt aufteilen

Bei Frameworks betrifft Lazy Loading nicht nur Medien, sondern auch JavaScript-Code. Ein Support-Chat, ein komplexer Diagramm-Editor oder ein Modal muss nicht unbedingt im ersten Paket landen, wenn er erst nach einem Klick geöffnet wird. Dynamische Imports teilen den Bundle in kleinere Dateien, die erst bei Bedarf angefordert werden.

In React wird dafür häufig lazy zusammen mit Suspense verwendet. Der Fallback zeigt während des Ladevorgangs einen definierten Zustand an, statt eine leere Fläche oder einen Fehler zu hinterlassen:

import { lazy, Suspense } from "react";

const ProductConfigurator = lazy(
  () => import("./ProductConfigurator")
);

export default function ProductPage() {
  return (
    Konfigurator wird geladen ...}>
      
    
  );
}

Ich würde aber nicht jede kleine Komponente auf diese Weise auslagern. Viele winzige Dateien erzeugen zusätzliche Requests und Ladezustände, die den Code komplizierter machen. Sinnvoll ist die Aufteilung vor allem bei großen, selten genutzten oder interaktiven Bereichen.

Next.js bietet mit dynamischen Imports einen ähnlichen Weg. Ein Modal, das erst nach einer Nutzeraktion benötigt wird, kann beispielsweise so eingebunden werden:

import dynamic from "next/dynamic";

const HelpModal = dynamic(
  () => import("./HelpModal"),
  { ssr: false }
);

ssr: false sollte nicht reflexartig eingesetzt werden. Es verhindert die serverseitige Darstellung der Komponente und passt daher nur für Inhalte, die tatsächlich Browser-APIs benötigen oder erst nach einer Interaktion erscheinen. Für sichtbaren Hauptinhalt ist Server Rendering meist die bessere Ausgangslage.

In Vue übernimmt defineAsyncComponent eine vergleichbare Aufgabe. Der entscheidende Punkt bleibt bei allen Frameworks gleich: Der Code darf erst dann vom Server angefordert werden, wenn die Komponente gebraucht wird. Ein Lade-, Fehler- und Wiederholungszustand gehört dabei von Anfang an zum Konzept.

Native Browser-Funktion oder JavaScript-Observer

Für Standardfälle bevorzuge ich die native Browser-Unterstützung. Eine JavaScript-Lösung mit der Intersection Observer API lohnt sich erst, wenn der Auslösemoment genauer gesteuert werden muss, etwa bei individuellen Vorlaufabständen, speziellen Animationen oder Hintergrundbildern in komplexen Komponenten.

Ansatz Geeignet für Stärke Grenze
loading="lazy" Bilder und Iframes Wenig Code, gute Wartbarkeit Weniger genaue Steuerung des Startzeitpunkts
Intersection Observer Individuelle Komponenten und Medien Flexibler Abstand zum Viewport Zusätzliche Logik und Fehlerfälle
Dynamischer Import JavaScript-Komponenten Kleinere Initial-Bundles Lade- und Fehlerzustände müssen gestaltet werden
preload="none" Nicht sichtbare Videos und Audioinhalte Verhindert frühe Medienanfragen Der Start nach Interaktion kann spürbar sein

Die ältere Methode mit data-src und einem Scroll-Event würde ich nur noch aus Kompatibilitätsgründen verwenden. Sie kann funktionieren, bringt aber mehr JavaScript, mehr Zustände und zusätzliche Möglichkeiten für Fehler mit. Die native Variante ist laut MDN für typische Bilder und Iframes der naheliegende Einstieg.

So integriere und prüfe ich die Technik

Eine gute Umsetzung beginnt nicht mit einem Plugin, sondern mit einer Bestandsaufnahme. Ich öffne die Seite auf einem mobilen Gerät oder mit gedrosseltem Netzwerk und prüfe, welche Ressourcen vor dem ersten Scrollen wirklich benötigt werden. Daraus entsteht eine einfache Priorisierung:

  1. Sichtbaren Inhalt markieren, besonders Hero-Bild, Überschrift, Navigation und primäre Aktion.
  2. Ressourcen unterhalb des Viewports identifizieren, etwa Galerien, Karten, Videos und Werbemittel.
  3. Native Attribute oder dynamische Imports einsetzen, abhängig vom Ressourcentyp.
  4. Platzhalter und Abmessungen festlegen, damit sich das Layout nicht verschiebt.
  5. Vorher und nachher messen, statt nur auf ein subjektiv schnelleres Gefühl zu vertrauen.

In den Chrome DevTools kontrolliere ich im Netzwerk-Tab, wann die jeweilige Datei angefordert wird. Mit deaktiviertem Cache und einer simulierten Mobilfunkverbindung wird sichtbar, ob ein Bild tatsächlich erst beim Annähern geladen wird. Zusätzlich helfen Lighthouse und reale Felddaten, weil Laborwerte allein nicht jede Gerätekombination abbilden.

Besonders wichtig sind LCP, CLS und INP. LCP zeigt, wie schnell das wichtigste sichtbare Element erscheint, CLS misst Layoutverschiebungen und INP bewertet die Reaktionsfähigkeit auf Interaktionen. Ein besserer Wert bei der initialen Datenmenge ist kein Erfolg, wenn dafür das Hero-Bild zu spät erscheint oder ein Button erst nach langem JavaScript-Laden reagiert.

Die Messung sollte mindestens einmal mit leerem Cache und einmal mit wiederkehrendem Besuch erfolgen. Caching kann die zweite Variante stark beschleunigen. Für eine belastbare Entscheidung prüfe ich zusätzlich unterschiedliche Bildschirmgrößen, langsame Verbindungen und den Fall, dass JavaScript blockiert oder fehlschlägt.

Die Fehler, die Performance kosten

Der häufigste Fehler ist das pauschale Lazy Loading aller Bilder. Dadurch wird manchmal auch das wichtigste Bild der Seite verzögert, obwohl es sofort sichtbar ist. Automatische Regeln ohne Ausnahme für den ersten Viewport sind deshalb riskant.

Ein zweites Problem sind fehlende Abmessungen. Wenn der Browser die Höhe eines nachgeladenen Bildes nicht kennt, springt der nachfolgende Inhalt beim Einfügen nach unten. Das stört nicht nur beim Lesen, sondern kann auch die Bewertung der visuellen Stabilität verschlechtern.

Auch ein Platzhalter darf nicht mit der eigentlichen Ressource konkurrieren. Ein großes Blur-Bild, ein unnötiger Preload oder ein schweres Skeleton kann den Netzwerkkontingent wieder verbrauchen, das durch das verzögerte Laden eingespart werden sollte. Ich halte Platzhalter deshalb leicht, proportional und funktional.

Bei Komponenten wird oft nur der Erfolgsfall bedacht. Scheitert der dynamische Import, bleibt eine leere Fläche zurück. Ein klarer Fehlerzustand mit Wiederholen-Schaltfläche ist besonders bei Checkout, Login und Konfigurationen wichtig, weil dort ein fehlendes Modul den gesamten Ablauf blockieren kann.

Schließlich darf Accessibility nicht verloren gehen. Bilder brauchen sinnvolle Alternativtexte, interaktive Komponenten müssen per Tastatur erreichbar bleiben und Ladezustände sollten verständlich angekündigt werden. Performance und Zugänglichkeit sind keine Gegensätze, solange der Inhalt nicht nur schneller, sondern auch verlässlich nutzbar bleibt.

Ein pragmatischer Ladeplan für die nächste Veröffentlichung

Für eine typische Content-Seite würde ich zuerst das Hero-Bild, Logo, CSS und den unmittelbar sichtbaren Text priorisieren. Bilder in weiteren Abschnitten, eingebettete Videos und selten genutzte Widgets kommen danach. Bei einer Webanwendung verschiebt sich der Schwerpunkt zu dynamischen Imports für Funktionen, die erst durch Klick, Navigation oder bestimmte Rollen benötigt werden.

Die beste Lösung ist selten die technisch spektakulärste. In der Praxis bringen korrekte Bildgrößen, passende Prioritäten und weniger unnötiges JavaScript meist mehr als ein kompliziertes Eigenbau-System. Wer jede Ressource nach ihrer tatsächlichen Bedeutung für den ersten Bildschirm beurteilt und die Änderung anschließend misst, erhält eine schnelle Seite ohne überraschende Nebenwirkungen.

Häufig gestellte Fragen

Hero-Bilder im ersten Viewport und das wichtigste LCP-Bild sollten normalerweise sofort geladen werden. Für solche Ressourcen kann fetchpriority="high" sinnvoll sein, während loading="lazy" die Darstellung verschlechtern kann.

Bei Bildern sollten width und height angegeben werden, damit der Browser den benötigten Platz früh reserviert. Zusätzlich helfen srcset und sizes, passende Bildgrößen auszuliefern, während Platzhalter leicht und proportional bleiben sollten.

Dynamische Imports eignen sich besonders für große, selten genutzte oder interaktive Bereiche, die erst nach einem Klick oder einer Navigation benötigt werden. React verwendet dafür häufig lazy und Suspense, Vue defineAsyncComponent und Next.js dynamic. Lade-, Fehler- und Wiederholungszustände sollten dabei eingeplant werden.

In den Chrome DevTools zeigt der Netzwerk-Tab, wann Ressourcen angefordert werden. Mit deaktiviertem Cache und gedrosseltem Mobilfunk lassen sich die Effekte testen. Lighthouse sowie Felddaten helfen zusätzlich, LCP, CLS und INP vor und nach der Änderung zu vergleichen.

Artikel bewerten

Bewertung: 0.00 Stimmenanzahl: 0

Tags:

lazy loading code-splitting intersection observer core web vitals iframes

Beitrag teilen

Edwin Appel

Edwin Appel

Mein Name ist Edwin Appel und seit 11 Jahren beschäftige ich mich intensiv mit den sich ständig weiterentwickelnden Welten der Webentwicklung, der digitalen Strategie und der künstlichen Intelligenz. Diese Themen sind für mich mehr als nur berufliche Felder; sie sind faszinierende Bereiche, in denen ich gerne komplexe Zusammenhänge aufschlüssele und verständlich mache. Auf metawebart.de teile ich meine Erkenntnisse und Erfahrungen, um Ihnen dabei zu helfen, die digitalen Herausforderungen unserer Zeit besser zu verstehen und zu meistern. Mein Ziel ist es, Ihnen stets fundierte, nachvollziehbare und aktuelle Informationen zu liefern, die Ihnen bei Ihrer eigenen digitalen Reise nützlich sind.

Kommentar schreiben