Stel offscreen afbeeldingen uit op mobiel

Stel offscreen afbeeldingen uit op mobiel

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-01-23

Mobiele Afbeelding Uitstel: de standaard

Mobiele prestaties worden vaak tegengehouden door netwerklatentie (RTT) en main-thread CPU beschikbaarheid. Het uitstellen van offscreen afbeeldingen op mobiel pakt beide aan door bandbreedteconcurrentie op het kritieke renderingpad te voorkomen en de kosten voor het decoderen van afbeeldingen over de sessieduur te verdelen.

Dit document legt uit hoe je afbeeldingen op mobiel effectief kunt uitstellen, wanneer je het moet gebruiken en behandelt de specifieke mechanische beperkingen van mobiele viewports.

1. Stel offscreen afbeeldingen uit op mobiel: native lazy loading

Wanneer een browser een pagina laadt, opent hij een beperkt aantal parallelle verbindingen (afhankelijk van veel factoren, maar 6 per domein is een gewoon gemiddelde). Als deze verbindingen worden gebruikt voor het downloaden van offscreen afbeeldingen (bijv. een footer-logo of carrousel-slide), zal de download van kritieke bronnen (meestal de LCP-afbeelding, belangrijke scripts en lettertypen concurreren om slots en bandbreedte). Dit fenomeen, bekend als Netwerkconcurrentie (Network Contention), vermindert direct de Core Web Vitals.

Door offscreen afbeeldingen uit te stellen met behulp van het native loading attribuut, kunnen we belangrijke bronnen prioriteren en het Critical Rendering Path optimaliseren. De browser haalt alleen op wat onmiddellijk zichtbaar is, en reserveert bandbreedte voor de assets die strikt de First Contentful Paint (FCP) en de Largest Contentful Paint (LCP) beïnvloeden. De native lazy loading-methode besteedt deze prioriteringslogica uit aan het veel snellere interne mechanisme van de browser, waardoor oude en trage JavaScript-bibliotheken overbodig worden.

Implementatie

Voeg voor alle afbeeldingen onder de initiële viewport ("the fold") het loading="lazy" attribuut toe.

<!-- Standaard Uitgestelde Afbeelding -->
<img src="product-detail.jpg"
     loading="lazy"
     alt="Zijaanzicht van het chassis"
     width="800"
     height="600"
     decoding="async">

Hoe lazy loading werkt op mobiel: De Browser Heuristiek

Native lazy loading is superieur aan JavaScript-oplossingen omdat de browser de laaddrempel (wanneer een afbeelding wordt geactiveerd voor download) aanpast op basis van het Effectieve Verbindingstype (ECT).

  • Op 4G/WiFi: De Blink-engine (Chrome/Edge) hanteert een conservatieve drempel (bijv. 1250px). Het gaat uit van lage latentie en haalt de afbeelding alleen op wanneer de gebruiker relatief dicht bij de viewport is.
  • Op 3G/Slow-2G: De drempel wordt groter (bijv. 2500px). De browser initieert het verzoek veel eerder relatief ten opzichte van de scrollpositie om hoge round-trip-tijden te compenseren, zodat de afbeelding klaar is voordat de gebruiker deze in beeld scrolt.

Kritieke Uitzondering: De LCP-kandidaat

Een veelvoorkomende prestatieregressie treedt op wanneer ontwikkelaars loading="lazy" toepassen op het Largest Contentful Paint (LCP) element (meestal de hero-afbeelding). Dit vertraagt de fetch totdat de lay-out voltooid is.

Correcte LCP-strategie: De LCP-afbeelding moet eager-geladen en geprioriteerd worden.

<!-- Hero Afbeelding: Eager en Geprioriteerd -->
<img src="hero.jpg"
     alt="Zomercollectie"
     width="1200"
     height="800"
     loading="eager"
     fetchpriority="high"

2. Mobiele complexiteiten: Viewport en Touch

Mobiele viewports introduceren specifieke rendering-uitdagingen die de native implementatie robuuster afhandelt dan script-gebaseerde oplossingen.

  • De Viewport: Het zichtbare rechthoekige gebied van het browservenster. Op mobiel is dit dynamisch; het verandert van afmetingen op basis van apparaatoriëntatie (portret vs. landschap) en de staat van de browser chrome (URL-balken die intrekken).
  • The Fold: De exacte onderrand van de viewport. Het is de drempel die zichtbare inhoud scheidt van off-screen inhoud.
  • Above the Fold: Alle inhoud die onmiddellijk zichtbaar is na het laden van de pagina zonder te scrollen. Afbeeldingen hier zijn vaak kritiek en mogen bijna nooit lazy-geladen worden.
  • Below the Fold: Alle inhoud die zich verticaal voorbij de vouw bevindt. Deze inhoud is Niet-Kritiek en moet worden uitgesteld totdat de gebruiker er in de buurt scrolt.

De Dynamische Viewport

In mobiele browsers is de viewporthoogte (vh) vloeiend. Wanneer de gebruiker een touch-scroll initieert, trekken de URL-balk en navigatieknoppen vaak in, waardoor de grootte van het zichtbare gebied verandert.

Op JavaScript gebaseerde bibliotheken voor het uitstellen van afbeeldingen berekenen de viewporthoogte (window.innerHeight) meestal slechts één keer aan het begin van het laden van de pagina.  Wanneer mobiele browsers het zichtbare gebied dynamisch vergroten door de URL-balk te verbergen tijdens een scroll, blijven JavaScript-methoden de oude, kleinere hoogtewaarde gebruiken. Dit zorgde ervoor dat afbeeldingen ongeladen bleven, zelfs wanneer ze fysiek het uitgebreide viewportgebied binnenkwamen, wat leidde tot een slechte UX voor de bezoekers.

Native afhandeling lost dit probleem op omdat de interne layout-engine van de browser de visuele viewport automatisch bijhoudt, zodat triggers afgaan ongeacht wijzigingen in de viewportgrootte.

3. Mobiele Afbeeldingdecodering en CPU-beperking

Mobiele apparaten hebben beperkte CPU en het decoderen van afbeeldingen op mobiel kan relatief traag en duur zijn. Het converteren van een JPEG naar een bitmap vereist veel CPU-cycli. Op een mobiele processor kan het decoderen van een reeks grotere afbeeldingen de main-thread voor 50ms–100ms elk blokkeren, wat invoerlatentie veroorzaakt.

De Oplossing: content-visibility

Om dit op te lossen, kunnen we de CSS-eigenschap en waarde content-visibility: auto gebruiken. Deze eigenschap fungeert als een standaard voor "Lazy Rendering". Het instrueert de browser om de lay-out- en painting-fasen voor off-screen elementen volledig over te slaan. Het element bestaat in de DOM, maar het bestaat niet in de Render Tree totdat het de viewport nadert.

Omdat deze optimalisatie werkt door het renderen van de subtree van een element over te slaan, kun je het niet direct toepassen op een <img> tag (die geen subtree heeft). Je moet content-visibility toepassen op de productcontainer of afbeeldingskaart die deze afbeeldingen en de inhoud ervan host

@media (max-width: 768px) {
    .image-card, .product-card {
        /* Sla het renderen van de container en zijn kinderen over */
        content-visibility: auto;
        
        /* Essentieel: Voorkomt dat de container instort tot 0px hoogte */
        contain-intrinsic-size: auto 300px;
    }
}

Dit zorgt ervoor dat zelfs als een afbeelding wordt gedownload, de browser de lay-out/paint-kosten niet betaalt totdat de gebruiker er daadwerkelijk naartoe scrolt.

4. Oude Methodieken: Waarom ze te vermijden

Vóór native ondersteuning vertrouwden ontwikkelaars op JavaScript voor het uitstellen van mobiele afbeeldingen. Deze methoden worden nog steeds veel gebruikt, maar moeten als technische schuld worden beschouwd!

Het "Scroll Handler" Tijdperk (2010–2016)

Vroege implementaties koppelden event listeners aan het scroll event.

// VEROUDERD: Niet gebruiken
window.addEventListener('scroll', () => {
    images.forEach(img => {
        if (img.getBoundingClientRect().top < window.innerHeight) {
            img.src = img.dataset.src;
        }
    });
});

Main Thread Blocking: Het scroll event vuurt tientallen keren per seconde. Het uitvoeren van logica en het berekenen van lay-out (getBoundingClientRect) tijdens actief scrollen veroorzaakte frame drops (jank).

Layout Thrashing: Het opvragen van geometrische eigenschappen dwingt de browser om de lay-outstijl synchroon opnieuw te berekenen, een rekenintensieve operatie op mobiele CPU's. 

Het IntersectionObserver Tijdperk (2016–2019)

De IntersectionObserver API verbeterde de prestaties door asynchroon veranderingen in elementzichtbaarheid te observeren. 

// VEROUDERD: Gebruik native loading waar mogelijk
const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src;
            observer.unobserve(img);
        }
    });
});

Script Afhankelijkheid: Het vereist JavaScript-uitvoering. Als de main thread bezig is met het hydrateren van een framework (React/Vue), blijven de afbeeldingen ongeladen, zelfs als ze in de viewport staan.

Gebrek aan Netwerkbewustzijn: In tegenstelling tot native loading gebruikt IntersectionObserver vaste marges (bijv. rootMargin: '200px'). Het breidt zijn buffer niet automatisch uit op trage netwerken, wat leidt tot "witte flitsen" voor gebruikers op slechte verbindingen.


Performance is a Feature.

Treating speed as an afterthought fails. Build a performance culture with a dedicated 2-sprint optimization overhaul.

Initialize Project >>

  • 2-Sprint Overhaul
  • Culture Building
  • Sustainable Speed
Stel offscreen afbeeldingen uit op mobiel Core Web Vitals Stel offscreen afbeeldingen uit op mobiel