Lazy loading images : pourquoi et comment l’implémenter

Dans cet article

  • Le lazy loading réduit le temps de chargement initial d’une page de 40 à 70 % selon le nombre d’images
  • L’attribut natif loading= »lazy » est supporté par plus de 95 % des navigateurs en 2026
  • Google recommande officiellement le lazy loading comme facteur d’amélioration des Core Web Vitals
  • Une implémentation incorrecte peut nuire au SEO si les images ne sont pas indexables par les robots
  • Le fallback JavaScript avec Intersection Observer couvre les cas non supportés nativement
  • Sur WordPress, le lazy loading est activé par défaut depuis la version 5.5, mais nécessite des ajustements

Depuis que je travaille comme développeur web freelance dans la Loire, je constate le même problème sur la majorité des sites que j’audite : des pages lourdes, bourrées d’images chargées simultanément, qui mettent plusieurs secondes à s’afficher. Le lazy loading images est la solution la plus simple et la plus efficace pour résoudre ce problème. Je vais vous expliquer concrètement pourquoi et comment l’implémenter, que vous soyez sur un site statique, un projet JavaScript ou WordPress.

Qu’est-ce que le lazy loading images

Le lazy loading, ou chargement différé, est une technique qui consiste à ne charger les images que lorsqu’elles deviennent visibles dans la fenêtre du navigateur. Concrètement, au lieu de télécharger les 30 ou 50 images d’une page dès l’ouverture, le navigateur ne charge que celles qui apparaissent à l’écran. Les autres sont téléchargées au fur et à mesure que l’utilisateur fait défiler la page.

Le principe est simple : pourquoi forcer le navigateur à télécharger une image située tout en bas de la page alors que le visiteur ne la verra peut-être jamais ? Sans lazy loading, chaque image déclenche une requête HTTP dès le chargement du DOM, ce qui consomme de la bande passante et ralentit l’affichage du contenu visible. Avec le lazy loading, seules les images proches du viewport sont chargées immédiatement. Les autres sont remplacées par un placeholder léger (une couleur unie, un SVG flou ou simplement un espace vide) jusqu’à ce que le scroll de l’utilisateur les approche.

Cette technique n’est pas nouvelle. Les développeurs l’utilisent depuis plus de dix ans via des bibliothèques JavaScript. Mais depuis 2019, les navigateurs proposent une implémentation native qui simplifie considérablement la mise en place. Selon les données de web.dev, la documentation officielle de Google sur le lazy loading, cette approche native est désormais la méthode recommandée pour la majorité des projets web.

L'attribut loading lazy s'ajoute directement dans le code HTML des balises image
L’attribut loading lazy s’ajoute directement dans le code HTML des balises image

Pourquoi implémenter le lazy loading sur vos images

L’impact du lazy loading sur la performance d’un site est mesurable et significatif. Voici les raisons concrètes pour lesquelles je l’implémente systématiquement sur chaque projet.

Réduction du temps de chargement initial

Sur une page e-commerce avec 40 produits affichés, le lazy loading peut réduire le poids initial de la page de 60 à 80 %. Au lieu de charger 8 Mo d’images d’un coup, le navigateur ne télécharge que 1 à 2 Mo au départ. Le contenu visible s’affiche beaucoup plus rapidement, ce qui améliore directement l’expérience utilisateur et réduit le taux de rebond.

Amélioration des Core Web Vitals

Google utilise trois métriques principales pour évaluer la performance d’une page : le LCP (Largest Contentful Paint), le FID (First Input Delay) et le CLS (Cumulative Layout Shift). Le lazy loading agit directement sur le LCP en libérant de la bande passante pour charger plus vite l’élément principal de la page. Il réduit également le FID en diminuant le nombre de tâches concurrentes du navigateur. Ces métriques influencent directement votre positionnement dans les résultats Google.

Économie de bande passante

En moyenne, 50 % des visiteurs ne scrollent pas au-delà de la première moitié d’une page. Sans lazy loading, vous payez le transfert d’images que personne ne voit. Sur un site avec 100 000 visiteurs mensuels, l’économie de bande passante peut atteindre plusieurs centaines de gigaoctets par mois. C’est particulièrement pertinent pour les blogs à fort trafic et les sites hébergés sur des forfaits à bande passante limitée.

Meilleure expérience mobile

Sur mobile, les connexions sont souvent plus lentes et les forfaits data limités. Le lazy loading permet à vos visiteurs mobiles de consommer moins de données tout en accédant plus vite au contenu qu’ils cherchent. C’est un facteur décisif quand on sait que plus de 60 % du trafic web mondial provient des appareils mobiles.

Lazy loading natif avec l’attribut HTML loading= »lazy »

La méthode la plus simple pour implémenter le lazy loading images est d’utiliser l’attribut natif loading= »lazy » introduit dans la spécification HTML. Aucun JavaScript n’est nécessaire : une seule ligne de code suffit.

Syntaxe de base

Voici comment transformer une balise image classique en image lazy-loadée :

<!-- Chargement classique -->
<img src="photo-produit.jpg" alt="Description du produit" width="800" height="600">

<!-- Avec lazy loading natif -->
<img src="photo-produit.jpg" alt="Description du produit" width="800" height="600" loading="lazy">

C’est aussi simple que cela. L’attribut loading accepte trois valeurs :

  • lazy : l’image est chargée uniquement quand elle s’approche du viewport
  • eager : l’image est chargée immédiatement (comportement par défaut)
  • auto : le navigateur décide lui-même de la stratégie de chargement

Règles importantes pour le LCP

Attention, il ne faut jamais appliquer loading= »lazy » aux images visibles dès le premier affichage de la page (above the fold). L’image principale d’un article, le hero banner ou le logo du site doivent rester en loading= »eager ». Si vous appliquez le lazy loading à l’image LCP, vous dégradez votre score au lieu de l’améliorer, car le navigateur retarde le chargement de l’élément le plus important.

Ma règle en pratique : les deux ou trois premières images de la page restent en eager. Toutes les suivantes passent en lazy. C’est une approche que je recommande selon les bonnes pratiques documentées par MDN Web Docs.

Compatibilité navigateurs

En 2026, l’attribut loading= »lazy » est supporté par Chrome, Firefox, Edge, Safari et Opera, soit plus de 95 % du trafic mondial. Les navigateurs qui ne le supportent pas ignorent simplement l’attribut et chargent l’image normalement. Il n’y a donc aucun risque de régression.

Avec les iframes

Le lazy loading natif fonctionne aussi sur les iframes, ce qui est particulièrement utile pour les vidéos YouTube ou les cartes Google Maps intégrées :

<iframe src="https://www.youtube.com/embed/xxxxx" loading="lazy" width="560" height="315" title="Titre de la vidéo"></iframe>
L'onglet Network des DevTools permet de vérifier le chargement progressif des images
L’onglet Network des DevTools permet de vérifier le chargement progressif des images

Implémentation JavaScript avec Intersection Observer

Pour les cas qui nécessitent un contrôle plus fin (animations au scroll, placeholder personnalisé, seuil de déclenchement configurable), l’API Intersection Observer est la solution JavaScript moderne. C’est d’ailleurs le mécanisme que les navigateurs utilisent en interne pour l’attribut natif.

Le principe

Au lieu de placer l’URL de l’image dans l’attribut src, on la stocke dans un attribut data-src. Un script JavaScript surveille le scroll et remplace data-src par src quand l’image entre dans le viewport. Cette approche est plus complexe que la méthode native, mais elle offre une flexibilité maximale pour les développeurs JavaScript.

Code complet et fonctionnel

Voici l’implémentation que j’utilise sur mes projets sur mesure :

<!-- HTML : les images avec data-src -->
<img class="lazy" data-src="photo-1.jpg" alt="Description" width="800" height="600">
<img class="lazy" data-src="photo-2.jpg" alt="Description" width="800" height="600">

<script>
document.addEventListener('DOMContentLoaded', function() {
  const lazyImages = document.querySelectorAll('img.lazy');

  if ('IntersectionObserver' in window) {
    const observer = new IntersectionObserver(function(entries) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          const img = entry.target;
          img.src = img.dataset.src;
          if (img.dataset.srcset) {
            img.srcset = img.dataset.srcset;
          }
          img.classList.remove('lazy');
          img.classList.add('loaded');
          observer.unobserve(img);
        }
      });
    }, {
      rootMargin: '200px 0px'
    });

    lazyImages.forEach(function(img) {
      observer.observe(img);
    });
  } else {
    // Fallback : charger toutes les images directement
    lazyImages.forEach(function(img) {
      img.src = img.dataset.src;
    });
  }
});
</script>

Explication du code

Le paramètre rootMargin: ‘200px 0px’ indique au navigateur de commencer le chargement quand l’image se trouve à 200 pixels du viewport visible. Cela évite que l’utilisateur voie un espace vide en scrollant rapidement. Le fallback dans le bloc else assure que les images se chargent même sur les très vieux navigateurs qui ne supportent pas Intersection Observer.

Ajouter un effet de transition

Pour rendre le chargement plus fluide, j’ajoute systématiquement une transition CSS :

img.lazy {
  opacity: 0;
  transition: opacity 0.3s ease-in;
}

img.loaded {
  opacity: 1;
}

L’image apparaît en fondu au lieu de s’afficher brutalement, ce qui donne une sensation de fluidité à la navigation.

Lazy loading images sur WordPress

Depuis WordPress 5.5, le lazy loading natif est activé automatiquement sur toutes les images insérées via l’éditeur. WordPress ajoute l’attribut loading="lazy" à chaque balise <img> générée par les fonctions natives comme wp_get_attachment_image() et the_content(). Cependant, cette implémentation par défaut mérite quelques ajustements pour être optimale.

Ce que WordPress fait par défaut

WordPress ajoute loading="lazy" à toutes les images du contenu et aux images mises en avant. Depuis WordPress 5.9, le CMS exclut intelligemment la première image du contenu pour ne pas pénaliser le LCP. C’est un bon comportement par défaut, mais il ne couvre pas tous les cas, notamment les images ajoutées par des thèmes ou des constructeurs de page.

Optimiser le lazy loading WordPress sans plugin

Voici le code que j’ajoute dans le fichier functions.php des thèmes que je développe pour un contrôle plus précis :

// Désactiver le lazy loading sur le logo et le hero
function custom_lazy_loading_exclusions($value, $image, $context) {
    if ($context === 'the_content') {
        // Garder le comportement par défaut pour le contenu
        return $value;
    }
    // Désactiver pour les images de header/hero
    if (strpos($context, 'header') !== false || strpos($context, 'hero') !== false) {
        return false;
    }
    return $value;
}
add_filter('wp_img_tag_add_loading_attr', 'custom_lazy_loading_exclusions', 10, 3);

Plugins recommandés pour aller plus loin

Si vous préférez ne pas toucher au code, certains plugins gèrent le lazy loading de manière plus avancée :

  • Perfmatters : léger, permet de contrôler précisément quelles images sont lazy-loadées
  • WP Rocket : inclut le lazy loading avec des options de placeholder et de seuil
  • Autoptimize : gratuit, ajoute le lazy loading avec un fallback JavaScript

Dans tous les cas, vérifiez que vous n’empilez pas plusieurs solutions de lazy loading. Avoir à la fois le natif WordPress, un plugin et un script personnalisé crée des conflits et peut dégrader les performances au lieu de les améliorer. C’est un point essentiel à vérifier lors d’une refonte de site web.

Comparatif des méthodes de lazy loading

Pour vous aider à choisir la méthode adaptée à votre projet, voici un comparatif détaillé basé sur mon expérience terrain :

Critère Attribut natif loading= »lazy » Intersection Observer (JS) Bibliothèque vanilla-lazyload Plugin WordPress
Difficulté Très facile Intermédiaire Facile Très facile
Poids ajouté 0 Ko ~1 Ko ~3 Ko (minifié) Variable (5 à 50 Ko)
Contrôle du seuil Non (géré par le navigateur) Oui (rootMargin configurable) Oui Selon le plugin
Placeholder personnalisé Non Oui Oui (LQIP, couleur, SVG) Selon le plugin
Support navigateurs 95 %+ 97 %+ 97 %+ 100 % (fallback inclus)
SEO-friendly Oui (recommandé par Google) Oui (si noscript prévu) Oui Oui
Cas d’usage idéal Sites statiques, blogs Applications sur mesure Sites complexes, galeries Sites WordPress

Mon conseil : commencez toujours par l’attribut natif. C’est la solution la plus légère et la plus fiable. N’ajoutez une couche JavaScript que si vous avez un besoin spécifique que le natif ne couvre pas (effet de transition, placeholder LQIP, chargement conditionnel basé sur la connexion réseau).

Sur mobile le lazy loading réduit la consommation de données et accélère le chargement
Sur mobile le lazy loading réduit la consommation de données et accélère le chargement

Erreurs fréquentes et bonnes pratiques

En douze ans de développement web, j’ai vu beaucoup d’implémentations de lazy loading qui faisaient plus de mal que de bien. Voici les erreurs les plus courantes et comment les éviter.

Erreur 1 : lazy-loader l’image LCP

C’est l’erreur numéro un. Si votre image hero ou votre image produit principale est en loading="lazy", le navigateur retarde son chargement alors qu’elle devrait être la priorité absolue. Résultat : un score LCP dégradé et un affichage lent du contenu principal. Utilisez même fetchpriority="high" sur l’image LCP pour accélérer encore son chargement :

<img src="hero.jpg" alt="Image principale" width="1200" height="675" fetchpriority="high">

Erreur 2 : oublier les attributs width et height

Sans dimensions explicites, le navigateur ne peut pas réserver l’espace pour l’image avant son chargement. Quand l’image arrive, elle pousse le contenu vers le bas, ce qui provoque un Cumulative Layout Shift (CLS) élevé. Chaque image doit avoir ses attributs width et height ou être dimensionnée via CSS avec aspect-ratio. C’est un fondamental du développement HTML et CSS.

Erreur 3 : empiler plusieurs solutions

J’ai audité des sites WordPress qui avaient simultanément le lazy loading natif de WordPress, un plugin de cache avec sa propre implémentation, et un script jQuery ajouté par le thème. Résultat : des conflits, des images qui ne se chargent pas, et un JavaScript inutile qui alourdit la page. Une seule méthode suffit.

Erreur 4 : ne pas prévoir de fallback noscript

Si vous utilisez la méthode JavaScript (data-src), les robots de certains moteurs de recherche et les navigateurs avec JavaScript désactivé ne verront aucune image. Ajoutez toujours une balise <noscript> :

<img class="lazy" data-src="photo.jpg" alt="Description" width="800" height="600">
<noscript>
  <img src="photo.jpg" alt="Description" width="800" height="600">
</noscript>

Erreur 5 : ne pas optimiser les images elles-mêmes

Le lazy loading ne remplace pas l’optimisation des images. Charger en différé une image de 5 Mo, c’est toujours charger une image de 5 Mo. Avant d’implémenter le lazy loading, assurez-vous que vos images sont en format WebP ou AVIF, correctement dimensionnées et compressées. L’optimisation de la vitesse passe par la combinaison des deux approches.

Bonnes pratiques récapitulatives

  • Toujours spécifier width et height sur chaque image
  • Utiliser loading="eager" et fetchpriority="high" sur l’image LCP
  • Privilégier le lazy loading natif sauf besoin spécifique
  • Tester avec les DevTools en mode réseau lent (3G) pour vérifier le comportement
  • Compresser et convertir les images en WebP avant de les servir

Mesurer l’impact du lazy loading sur la performance

Implémenter le lazy loading sans mesurer son impact, c’est travailler à l’aveugle. Voici les outils et métriques que j’utilise systématiquement pour valider mes implémentations.

Google Lighthouse

Accessible directement dans les DevTools de Chrome (onglet Lighthouse), cet outil analyse votre page et vous donne un score de performance sur 100. Après activation du lazy loading, vous devriez observer une amélioration notable du LCP et du Speed Index. Lighthouse signale également les images qui devraient être lazy-loadées mais ne le sont pas, et inversement celles qui le sont à tort.

PageSpeed Insights

L’outil en ligne de Google combine des données de laboratoire (Lighthouse) et des données terrain (Chrome User Experience Report). Il montre l’impact réel du lazy loading sur vos vrais visiteurs. Suivez l’évolution de vos Core Web Vitals après déploiement pour confirmer les gains. Ces données influencent directement votre capacité à bien vous positionner sur Google.

Onglet Network des DevTools

C’est l’outil le plus concret pour vérifier que le lazy loading fonctionne. Ouvrez les DevTools, allez dans l’onglet Network, filtrez par Img, puis rechargez la page. Vous devriez voir uniquement les images above the fold se charger au départ. En scrollant, les autres images apparaissent progressivement dans la cascade réseau. Si toutes les images se chargent d’un coup, votre implémentation ne fonctionne pas.

WebPageTest

Pour une analyse plus poussée, WebPageTest permet de visualiser le waterfall complet du chargement depuis différentes localisations géographiques et connexions réseau. Vous pouvez comparer un test avant/après lazy loading et mesurer précisément le gain en nombre de requêtes initiales, en poids transféré et en temps de rendu.

Métriques clés à surveiller

  • LCP : doit diminuer (ou au minimum rester stable)
  • CLS : ne doit pas augmenter (sinon, il manque des dimensions sur les images)
  • Nombre de requêtes initiales : doit diminuer significativement
  • Poids total initial : doit diminuer de 30 % ou plus sur les pages riches en images
  • Speed Index : doit s’améliorer car le contenu visible se charge plus vite

Si vous constatez que le LCP se dégrade après implémentation, c’est probablement parce que l’image principale est en lazy loading. Corrigez cela en repassant l’image LCP en loading="eager". C’est un réflexe essentiel dans toute démarche d’amélioration de la vitesse d’un site.

Le lazy loading est également un point de contrôle important lors d’une migration HTTPS, car les URLs des images changent et il faut s’assurer que les attributs data-src sont bien mis à jour.

À retenir

  • Ajoutez loading= »lazy » à toutes les images situées sous la ligne de flottaison
  • Ne jamais lazy-loader l’image LCP : utilisez loading= »eager » et fetchpriority= »high »
  • Spécifiez width et height sur chaque image pour éviter les décalages de mise en page
  • Sur WordPress, vérifiez qu’une seule solution de lazy loading est active
  • Mesurez l’impact avec Lighthouse et PageSpeed Insights avant et après déploiement

Questions fréquentes

Le lazy loading nuit-il au référencement des images ?

Non, à condition d’utiliser l’attribut natif loading= »lazy » ou de prévoir un fallback noscript avec la méthode JavaScript. Googlebot exécute le JavaScript et peut voir les images lazy-loadées. L’attribut natif est recommandé par Google lui-même. Vos images restent parfaitement indexables et apparaissent dans Google Images sans problème.

Faut-il un plugin pour le lazy loading sur WordPress ?

Pas nécessairement. Depuis WordPress 5.5, le lazy loading natif est activé par défaut. Un plugin n’est utile que si vous avez besoin de fonctionnalités avancées comme les placeholders LQIP, le contrôle du seuil de déclenchement ou le lazy loading sur les images de fond CSS. Dans la majorité des cas, le comportement natif est suffisant.

Quelle est la différence entre loading= »lazy » et loading= »eager » ?

L’attribut loading= »lazy » indique au navigateur de différer le chargement de l’image jusqu’à ce qu’elle s’approche du viewport. L’attribut loading= »eager » force le chargement immédiat, c’est le comportement par défaut. Utilisez eager uniquement pour les images visibles dès le premier affichage de la page (hero, logo, première image du contenu).

Le lazy loading fonctionne-t-il avec les images de fond CSS (background-image) ?

L’attribut natif loading= »lazy » ne s’applique qu’aux balises img et iframe. Pour les images de fond CSS, vous devez utiliser JavaScript avec Intersection Observer. Le principe est le même : vous ajoutez la classe CSS contenant le background-image uniquement quand l’élément entre dans le viewport. Certaines bibliothèques comme vanilla-lazyload gèrent ce cas automatiquement.

Comment savoir si le lazy loading fonctionne correctement sur mon site ?

Ouvrez les DevTools de votre navigateur (F12), allez dans l’onglet Network et filtrez par type Img. Rechargez la page : seules les images visibles à l’écran doivent apparaître. Ensuite, scrollez lentement vers le bas et observez les nouvelles images se charger progressivement. Vous pouvez aussi utiliser l’audit Lighthouse qui signale les images non lazy-loadées.

Le lazy loading ralentit-il l’affichage des images quand on scrolle ?

Avec une implémentation correcte, non. Le navigateur commence à charger les images avant qu’elles n’entrent dans le viewport grâce à un seuil de pré-chargement. Avec l’attribut natif, Chrome utilise un seuil dynamique basé sur la vitesse de connexion. Avec Intersection Observer, vous pouvez configurer le rootMargin à 200 ou 300 pixels pour anticiper le chargement et éviter tout effet de latence visible.

Nathan Morel
Nathan Morel

Nathan Morel est développeur web freelance depuis 12 ans dans la Loire. Spécialisé WordPress et solutions sur mesure, il a accompagné plus de 200 PME et partage son expérience technique et entrepreneuriale sur NA Web.

Un projet web ? Discutons-en.

Diagnostic gratuit et devis sous 24h.

Me contacter

Votre site est lent ?

Optimiser mon site