SEO Technique

Les bonnes pratiques pour le lazy loading des images

Le lazy loading posé partout, même sur l'image du haut de page, peut coûter jusqu'à 12 points de performance et plomber votre LCP. Découvrez pourquoi ce réflexe bien intentionné sabote votre SEO, et comment l'appliquer correctement en 2026.

Les bonnes pratiques pour le lazy loading des images

Un client m'a envoyé un jour un audit d'agence avec une case rouge : « lazy loading non détecté sur les images de la page d'accueil ». Verdict de l'audit : -12 points de performance, correction estimée à une journée de dev. J'ai ouvert son site. Sa page d'accueil contenait exactement une image. Une seule. En haut, en pleine largeur, celle qu'on voit avant tout scroll. L'agence voulait la charger en différé. C'est-à-dire la faire disparaître au moment précis où elle compte le plus.

Ce n'est pas une anecdote isolée. Depuis que tout le monde a découvert l'attribut loading="lazy", on le pose sur tout ce qui bouge, parfois même sur ce qu'il ne faut surtout pas toucher. Et en 2026, avec le LCP sous surveillance rapprochée, ce réflexe coûte des points de classement à ceux qui le prennent à la légère.

Le lazy loading reste une excellente pratique. Mais c'est une pratique conditionnelle. Voici comment je l'applique sur mes projets aujourd'hui, y compris les cas où je l'évite volontairement.

Points clés à retenir

  • Ne jamais différer l'image du haut de page (above the fold) : c'est le LCP qui trinque.
  • L'attribut natif loading="lazy" suffit dans 90 % des cas. Intersection Observer reste utile pour du contrôle fin ou du chargement déclenché.
  • Toujours déclarer width et height (ou un aspect-ratio) pour éviter le CLS.
  • Le format compte autant que le déclencheur : AVIF ou WebP avant de parler de lazy loading.
  • Méfiez-vous des librairies qui promettent « un lazy loading parfait » : la plupart cassent le SEO de l'image ou chargent une dépendance de 40 ko pour rien.

Pourquoi un lazy loading d'images mal fait dégrade vos performances

L'idée du lazy loading est simple : charger une image seulement quand elle approche du viewport. Sur une page catalogue avec 60 vignettes, ça évite de télécharger 4 Mo d'un coup alors que l'utilisateur ne regardera peut-être que les six premières. Sur le papier, c'est du gagnant-gagnant : moins de bande passante, moins de travail pour le navigateur au chargement initial.

Le problème arrive quand on l'applique à l'aveugle. Le navigateur doit alors attendre d'être proche du bas de page pour demander l'image, recevoir la réponse, la décoder, puis l'afficher. Sur la première image visible, ce délai se transforme directement en retard de rendu. Et ce retard, Google le mesure comme votre LCP.

Le LCP, cette métrique qui ne pardonne pas

Le LCP (Largest Contentful Paint) mesure le moment où le plus gros élément visible de la page s'affiche. Sur la grande majorité des sites, cet élément est une image. Un budget correct se situe sous les 2,5 secondes. Or, si l'image héros est en lazy loading, vous ajoutez un aller-retour réseau supplémentaire au pire moment : celui où l'utilisateur attend le plus.

Bon, soyons clairs : la différence n'est pas toujours dramatique. Sur une connexion fibre, l'écart peut se limiter à 200-400 ms. Sur un mobile en 4G dégradée, ça peut grimper à plus d'une seconde. Sur un site d'e-commerce, cette seconde se traduit directement en taux de rebond.

Le seuil de déclenchement : le vrai levier

Personne ne vous le dit dans les tutos de base, mais le comportement du lazy loading dépend entièrement de quand le navigateur décide de charger. Avec l'attribut natif, ce seuil n'est pas paramétrable : le navigateur applique ses propres règles, généralement une marge de quelques centaines de pixels autour du viewport, variable selon la vitesse de connexion estimée. Sur Chrome récent, cette marge est généreuse, ce qui atténue le problème du LCP. Sur d'autres moteurs, c'est moins prévisible.

C'est précisément là qu'Intersection Observer prend le relais quand vous avez besoin de contrôle. Vous pouvez définir un rootMargin explicite, par exemple 600px ou même 200% de la hauteur du viewport, pour déclencher le chargement anticipé. Dans mes tests, un rootMargin de 600 à 800 px offre un bon compromis : les images arrivent avant que l'utilisateur ne les voie, sans pour autant tout charger à l'ouverture.

À retenir : le natif suffit pour le bas de page, l'Observer devient intéressant quand vous voulez maîtriser finement la distance d'anticipation.

Quand utiliser le lazy loading, et quand l'éviter absolument

La règle que j'applique est bête, mais elle m'a évité bien des ennuis : tout ce qui peut apparaître sans scroll ne doit jamais être différé. Le reste, oui.

  • L'image héros, le logo, la première vignette d'une grille, la bannière produit : chargement normal, avec fetchpriority="high" sur l'élément critique.
  • Les images situées en dessous de la ligne de flottaison : lazy loading, systématiquement.
  • Les iframes et vidéos intégrées plus bas dans la page : lazy loading également, mais attention aux embeds qui gèrent mal le différé.
  • Les images des carrousels : cas délicat, on en parle plus bas.

Le piège des carrousels et des onglets

Un carrousel affiche par défaut une seule image, mais en contient cinq, dix, parfois vingt. Si vous lazy-load tout le lot, les slides invisibles ne se chargent jamais, et au clic suivant, l'utilisateur voit un flash blanc le temps que l'image arrive. Moche.

La solution : charger la première slide en priorité normale, et différer les suivantes avec un seuil large, ou mieux, les précharger une fois la première affichée. Même logique pour les onglets et les accordéons : si un contenu caché est en lazy loading, il se chargera à l'ouverture, avec un délai perceptible. Pour ces cas, je préfère souvent désactiver le différé et anticiper le chargement en arrière-plan.

Le cas des images sous la ligne de flottaison mobile

Sur mobile, le viewport est étroit et haut. Résultat : ce qui est « en dessous » sur desktop peut très bien se retrouver visible sur un écran de téléphone. Si vous codez en pensant desktop, vous risquez de différer une image que le visiteur mobile voit immédiatement. C'est l'erreur que j'ai commise sur un site de recettes : la photo principale passait sous le pli sur mon écran de test, mais s'affichait au-dessus sur un petit iPhone. Le LCP mobile a souffert pendant deux semaines avant que je ne comprenne.

La parade : testez toujours sur un vrai petit écran, ou utilisez l'émulation mobile du navigateur avec les dimensions d'un appareil récent.

Lazy loading natif ou Intersection Observer : lequel choisir en 2026

Le débat n'est plus vraiment « natif contre librairie ». La question est de savoir quand l'attribut HTML ne suffit plus.

Lazy loading natif ou Intersection Observer : lequel choisir en 2026
Approche Quand l'utiliser Points de vigilance
loading="lazy" natif Images sous la ligne de flottaison, cas standards Seuil non paramétrable, comportement variable selon le navigateur
Intersection Observer Besoin de contrôle du seuil, chargements conditionnels, animations liées Nécessite du JS, à intégrer avec précaution pour ne pas bloquer le rendu
Librairies tierces Cas très spécifiques, projets legacy Poids JS ajouté, dépendance externe, souvent redondant avec le natif
Lazy loading + srcset Images responsives, plusieurs résolutions Bien vérifier que le bon fichier est choisi selon le viewport

Mon avis, que j'assume : dans la quasi-totalité des projets, le natif suffit. J'ai arrêté d'installer des librairies de lazy loading il y a deux ans, et mes scores n'ont pas baissé. Au contraire, j'ai gagné quelques dizaines de kilo-octets de JS à chaque fois.

L'interaction avec le CLS

Vous pouvez avoir un lazy loading impeccable et un CLS catastrophique. Le CLS (Cumulative Layout Shift) mesure les décalages de mise en page pendant le chargement. Si vos images n'ont pas de dimensions réservées dans le HTML, elles apparaissent en poussant le contenu vers le bas, et ça se voit.

La règle est simple et ancienne : déclarez toujours width et height sur vos balises <img>, ou bien utilisez aspect-ratio en CSS. Le navigateur peut alors réserver l'espace avant même que l'image n'arrive. Peu importe que la valeur soit exacte : le ratio est ce qui compte. Une image 1600×900 peut être déclarée en 16/9, le navigateur s'en contentera.

Sans cette précision, le lazy loading aggrave le CLS, puisque l'image manquante laisse un trou qui se comble brutalement à l'arrivée.

Le format et la compression : le levier avant le différé

Je vais être direct : si vos images pèsent 800 ko chacune, aucun lazy loading ne vous sauvera. Le meilleur gain de performance que j'ai obtenu sur un site client venait simplement de la conversion en AVIF. La page est passée de 3,2 Mo à 680 ko, sans toucher une ligne de JavaScript.

L'ordre d'action que je recommande :

  1. Convertir les images en WebP (fallback générique) et proposer de l'AVIF quand le support le permet.
  2. Redimensionner les fichiers à la taille réellement affichée, pas à la résolution du fichier source.
  3. Mettre en place un srcset avec plusieurs largeurs.
  4. Ensuite, ajuster le comportement de chargement.

Faire du lazy loading sur des images lourdes, c'est déplacer le problème, pas le résoudre. Vous chargez moins souvent, mais chaque chargement reste coûteux.

Servir le bon fichier selon le viewport

Un piège fréquent : déclarer un srcset et un lazy loading qui finissent par servir la grande image au mobile. Le navigateur choisit la source selon la largeur du viewport au moment où il déclenche le chargement. Si votre différé se déclenche trop tard, le choix peut se faire dans de mauvaises conditions, et vous téléchargez une version surdimensionnée pour rien. Ce n'est pas dramatique, mais c'est du gaspillage silencieux.

Testez avec l'onglet réseau du navigateur en conditions mobiles pour vérifier quel fichier est réellement téléchargé.

Ce que je fais systématiquement sur mes projets

Pour finir, voici la liste courte que j'applique aujourd'hui, sans exception :

  • Image héros : chargement normal, fetchpriority="high", jamais de différé.
  • Toutes les autres images : loading="lazy", avec dimensions réservées.
  • Format AVIF avec fallback WebP, dimensionnement à la taille d'affichage.
  • Intersection Observer uniquement quand j'ai besoin d'un seuil précis.
  • Test sur un vrai mobile, pas seulement dans l'émulateur.

Et cette fameuse page d'accueil avec une seule image dont je vous parlais au début ? J'ai retiré l'attribut lazy que l'agence voulait ajouter, mis le fetchpriority="high", converti l'image en AVIF. Le LCP est passé de 3,1 s à 1,4 s. Résultat : aucun lazy loading ajouté, et des scores nettement meilleurs.

C'est un peu l'ironie de la chose. Dans ma boîte à outils, le lazy loading est un outil puissant. Mais les meilleurs résultats viennent souvent de ce qu'on décide de ne pas faire. La prochaine fois qu'un audit vous suggère d'en ajouter partout, posez-vous une seule question : est-ce que cette image s'affiche avant ou après le premier scroll ? Votre réponse vaut mieux que n'importe quelle recommandation générique.

Charlotte Caron

Charlotte Caron

Charlotte Caron est journaliste, spécialisée dans les domaines du SEO technique et de l’optimisation des performances web. Depuis une dizaine d’années, elle couvre des sujets tels que l’architecture de l’information, le balisage sémantique et l’impact de la vitesse de chargement sur le référencement. Ses articles s’appuient sur une veille constante des mises à jour des moteurs de recherche et des bonnes pratiques techniques.

Voir tous les articles →