Offscreen-Bilder auf Mobilgeräten verzögern
Verzögern Sie Offscreen-Bilder auf Mobilgeräten
Verzögerung von mobilen Bildern: der Standard
Die mobile Leistung wird oft durch Netzwerklatenz (RTT) und Main-Thread-CPU-Verfügbarkeit gebremst. Das Verzögern von Offscreen-Bildern auf Mobilgeräten adressiert beides, indem Bandbreitenkonkurrenz auf dem kritischen Rendering-Pfad verhindert und die Bilddecodierungskosten über die Sitzungsdauer verteilt werden.
Dieses Dokument erklärt, wie man Bilder auf Mobilgeräten effektiv verzögert, wann man es verwendet, und geht auf die spezifischen mechanischen Einschränkungen mobiler Viewports ein.

1. Offscreen-Bilder auf Mobilgeräten verzögern: natives Lazy Loading
Wenn ein Browser eine Seite lädt, öffnet er eine begrenzte Anzahl paralleler Verbindungen (hängt von vielen Faktoren ab, aber 6 pro Domain ist ein gängiger Durchschnitt). Wenn diese Verbindungen zum Herunterladen von Offscreen-Bildern verwendet werden (z. B. ein Footer-Logo oder Karussell-Slide), konkurriert der Download kritischer Ressourcen (typischerweise das LCP-Bild, wichtige Skripte und Schriftarten) um Slots und Bandbreite. Dieses Phänomen, bekannt als Netzwerk-Konkurrenz (Network Contention), verschlechtert direkt die Core Web Vitals.
Durch das Verzögern von Offscreen-Bildern mit dem nativen loading-Attribut können wir wichtige Ressourcen priorisieren und den Critical Rendering Path optimieren. Der Browser ruft nur das ab, was sofort sichtbar ist, und reserviert Bandbreite für die Assets, die strikt den First Contentful Paint (FCP) und den Largest Contentful Paint (LCP) beeinflussen. Die native Lazy-Loading-Methode lagert diese Priorisierungslogik auf den viel schnelleren internen Mechanismus des Browsers aus und macht alte und langsame JavaScript-Bibliotheken überflüssig.
Implementierung
Fügen Sie für alle Bilder unterhalb des anfänglichen Viewports ("the fold") das loading="lazy"-Attribut hinzu.
<!-- Standard Verzögertes Bild -->
<img src="product-detail.jpg"
loading="lazy"
alt="Seitenansicht des Chassis"
width="800"
height="600"
decoding="async">
Wie Lazy Loading auf Mobilgeräten funktioniert: Die Browser-Heuristik
Natives Lazy Loading ist JavaScript-Lösungen überlegen, da der Browser den Ladeschwellenwert (wann ein Bild zum Download ausgelöst wird) basierend auf dem effektiven Verbindungstyp (ECT) anpasst.
- Auf 4G/WiFi: Die Blink-Engine (Chrome/Edge) verwendet einen konservativen Schwellenwert (z. B. 1250px). Sie geht von geringer Latenz aus und ruft das Bild nur ab, wenn der Benutzer relativ nah am Viewport ist.
- Auf 3G/Slow-2G: Der Schwellenwert erweitert sich (z. B. 2500px). Der Browser initiiert die Anforderung relativ zur Scrollposition viel früher, um hohe Round-Trip-Zeiten zu kompensieren und sicherzustellen, dass das Bild bereit ist, bevor der Benutzer es in den sichtbaren Bereich scrollt.
Kritische Ausnahme: Der LCP-Kandidat
Eine häufige Leistungsverschlechterung tritt auf, wenn Entwickler loading="lazy" auf das Largest Contentful Paint (LCP)-Element (typischerweise das Hero-Bild) anwenden. Dies verzögert den Abruf, bis das Layout abgeschlossen ist.
Korrekte LCP-Strategie: Das LCP-Bild muss eager-geladen und priorisiert werden.
<!-- Hero Bild: Eager und Priorisiert -->
<img src="hero.jpg"
alt="Sommerkollektion"
width="1200"
height="800"
loading="eager"
fetchpriority="high"> 2. Mobile Komplexitäten: Viewport und Touch
Mobile Viewports führen spezifische Rendering-Herausforderungen ein, die die native Implementierung robuster handhabt als skriptbasierte Lösungen.
- Der Viewport: Der sichtbare rechteckige Bereich des Browserfensters. Auf Mobilgeräten ist dieser dynamisch; er ändert seine Dimensionen basierend auf der Geräteausrichtung (Hochformat vs. Querformat) und dem Zustand des Browser-Chroms (URL-Leisten ziehen sich zurück).
- The Fold: Die exakte Unterkante des Viewports. Es ist der Schwellenwert, der sichtbaren Inhalt von Off-Screen-Inhalt trennt.
- Above the Fold: Jeder Inhalt, der sofort nach dem Laden der Seite ohne Scrollen sichtbar ist. Bilder hier sind oft kritisch und sollten fast nie lazy-geladen werden.
- Below the Fold: Jeder Inhalt, der sich vertikal hinter dem Falz befindet. Dieser Inhalt ist nicht kritisch und muss verzögert werden, bis der Benutzer in seine Nähe scrollt.

Der dynamische Viewport
In mobilen Browsern ist die Viewport-Höhe (vh) flüssig. Wenn der Benutzer ein Touch-Scrollen initiiert, ziehen sich die URL-Leiste und die Navigationssteuerungen oft zurück, wodurch sich die Größe des sichtbaren Bereichs ändert.
JavaScript-basierte Bildverzögerungsbibliotheken berechnen die Viewport-Höhe (window.innerHeight) normalerweise nur einmal zu Beginn des Seitenladens. Wenn mobile Browser den sichtbaren Bereich dynamisch ändern, indem sie die URL-Leiste während eines Scrollens ausblenden, verwenden JavaScript-Methoden weiterhin den alten, kleineren Höhenwert. Dies führte dazu, dass Bilder ungeladen blieben, selbst wenn sie physisch in den erweiterten Viewport-Bereich eintraten, was zu einer schlechten UX für die Besucher führte.
Die native Handhabung behebt dieses Problem, da die interne Layout-Engine des Browsers den visuellen Viewport automatisch verfolgt und sicherstellt, dass Trigger unabhängig von Änderungen der Viewport-Größe ausgelöst werden.
3. Mobile Bilddecodierung und CPU-Drosselung
Mobile Geräte haben eine begrenzte CPU und die Bilddecodierung auf Mobilgeräten kann relativ langsam und teuer sein. Die Konvertierung eines JPEG in eine Bitmap erfordert viele CPU-Zyklen. Auf einem mobilen Prozessor kann das Decodieren einer Sequenz größerer Bilder den Main-Thread für jeweils 50ms–100ms blockieren, was zu Eingabelatenz führt.
Die Lösung: content-visibility
Um dies zu lösen, können wir die CSS-Eigenschaft und den Wert content-visibility: auto verwenden. Diese Eigenschaft fungiert als Standard für "Lazy Rendering". Sie weist den Browser an, die Layout- und Painting-Phasen für Off-Screen-Elemente vollständig zu umgehen. Das Element existiert im DOM, aber es existiert nicht im Render-Tree, bis es sich dem Viewport nähert.
Da diese Optimierung funktioniert, indem das Rendern des Unterbaums eines Elements übersprungen wird, können Sie sie nicht direkt auf ein <img>-Tag anwenden (das keinen Unterbaum hat). Sie sollten content-visibility auf den Produktcontainer oder die Bildkarte anwenden, die diese Bilder und ihren Inhalt hostet
@media (max-width: 768px) {
.image-card, .product-card {
/* Rendern des Containers und seiner Kinder überspringen */
content-visibility: auto;
/* Wesentlich: Verhindert, dass der Container auf 0px Höhe zusammenbricht */
contain-intrinsic-size: auto 300px;
}
}
Dies stellt sicher, dass, selbst wenn ein Bild heruntergeladen wird, der Browser die Layout-/Paint-Kosten nicht zahlt, bis der Benutzer tatsächlich dorthin scrollt.
4. Legacy-Methodologien: Warum man sie vermeiden sollte
Vor der nativen Unterstützung verließen sich Entwickler auf JavaScript für die mobile Bildverzögerung. Diese Methoden sind immer noch weit verbreitet, sollten aber als technische Schuld betrachtet werden!
Die "Scroll Handler" Ära (2010–2016)
Frühe Implementierungen hängten Event-Listener an das Scroll-Ereignis an.
// VERALTET: Nicht verwenden
window.addEventListener('scroll', () => {
images.forEach(img => {
if (img.getBoundingClientRect().top < window.innerHeight) {
img.src = img.dataset.src;
}
});
});
Main Thread Blocking: Das Scroll-Ereignis feuert Dutzende Male pro Sekunde. Das Ausführen von Logik und Berechnen des Layouts (getBoundingClientRect) während des aktiven Scrollens verursachte Frame-Drops (Jank).
Layout Thrashing: Das Abfragen geometrischer Eigenschaften zwingt den Browser, den Layout-Stil synchron neu zu berechnen, eine rechenintensive Operation auf mobilen CPUs.
Die IntersectionObserver Ära (2016–2019)
Die IntersectionObserver API verbesserte die Leistung, indem sie Änderungen der Elementsichtbarkeit asynchron beobachtete.
// VERALTET: Verwenden Sie natives Loading wo möglich
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
Skriptabhängigkeit: Es erfordert JavaScript-Ausführung. Wenn der Main-Thread damit beschäftigt ist, ein Framework (React/Vue) zu hydrieren, bleiben die Bilder ungeladen, selbst wenn sie im Viewport sind.
Mangel an Netzwerkbewusstsein: Im Gegensatz zum nativen Loading verwendet IntersectionObserver feste Ränder (z. B. rootMargin: '200px'). Es erweitert seinen Puffer in langsamen Netzwerken nicht automatisch, was zu "weißen Blitzen" für Benutzer mit schlechten Verbindungen führt.
Stop debating in Jira.
Get a definitive answer on your performance issues. I deliver a granular breakdown of your critical rendering path.
- Definitive Answers
- Granular Breakdown
- Critical Path Analysis