Le lazy loading, c’est-à-dire le chargement différé des images, est l’une des optimisations les plus connues et les plus simples à appliquer. Le principe est intuitif : pourquoi télécharger tout de suite des dizaines d’images alors que l’utilisateur ne les verra qu’en faisant défiler la page, ou peut-être jamais ? Les reporter libère de la bande passante et des ressources pour ce qui est vraiment nécessaire au premier coup d’œil, et sur les pages longues l’économie de données transférées peut être énorme.
Précisément parce qu’il est si simple, il est pourtant souvent appliqué à tout, sans distinction. Et appliqué à la mauvaise image, le lazy loading n’accélère pas la page : il la ralentit, et dégrade exactement la métrique qui dépend le plus des images, le Largest Contentful Paint. Dans cet article, nous voyons comment fonctionne le chargement différé natif, quand l’utiliser, quand l’éviter et comment WordPress le gère.
Comment fonctionne le lazy loading natif
Pendant des années, le chargement différé a exigé des bibliothèques JavaScript qui remplaçaient l’attribut src par un data-src et le rétablissaient quand l’image approchait de l’écran. Aujourd’hui, tous les principaux navigateurs prennent en charge l’attribut natif loading, pour les images et les iframes :
<img src="galleria-1.webp" width="800" height="600" loading="lazy" alt="…">
<iframe src="https://www.youtube-nocookie.com/embed/…" loading="lazy" title="…"></iframe>
Avec loading="lazy", le navigateur ne télécharge pas l’image tant qu’elle n’est pas à une certaine distance de l’écran. Il n’attend pas qu’elle soit visible : il la charge avec une marge de sécurité, de sorte qu’elle soit prête quand l’utilisateur arrive à son niveau. Dans Chrome, cette marge est d’environ 1 250 pixels sur les connexions rapides et d’environ 2 500 pixels sur les connexions lentes, où il faut plus de temps. La valeur par défaut, loading="eager", correspond au comportement normal : télécharger immédiatement.
L’avantage de la solution native sur les bibliothèques est considérable. Pas besoin de JavaScript, donc pas de code à télécharger ni à exécuter ; le navigateur connaît la vitesse de la connexion et adapte la marge ; et l’image reste un élément img normal avec son src, lisible par n’importe quel outil, moteurs de recherche compris.
L’erreur la plus courante : l’image LCP différée
Le problème survient quand loading="lazy" se retrouve sur l’image la plus importante de la page : la photo d’ouverture, l’image principale d’une fiche produit, la couverture d’un article. C’est presque toujours l’élément LCP, et le différer a un effet précis. Normalement, le navigateur découvre les images en lisant le HTML, grâce au preload scanner, et les demande tout de suite, en parallèle des feuilles de style et des scripts. Une image différée, en revanche, ne peut pas être demandée tant que le navigateur ne sait pas où elle se trouve dans la page, c’est-à-dire tant qu’il n’a pas téléchargé le CSS et calculé la mise en page. C’est alors seulement qu’il découvre qu’elle est visible et lance le téléchargement.
Le retard qui en résulte peut facilement dépasser une seconde sur mobile, et s’ajoute directement au LCP. Lighthouse le signale par un avertissement spécifique quand l’image LCP a été chargée en lazy loading, et c’est l’une des suggestions les plus fréquentes dans les rapports sur les sites WordPress. La correction est simple : retirer loading="lazy" de cette image et, mieux encore, lui donner la priorité maximale avec fetchpriority="high", comme l’explique l’article sur le LCP.
Avec les bibliothèques JavaScript, le dommage est encore plus grand. Une image avec data-src n’est pas une image pour le preload scanner : le navigateur ne la voit pas tant que le script n’a pas été téléchargé, exécuté et n’a pas calculé la position des éléments. Sur l’image LCP, cela peut représenter des secondes de retard, et c’est pourquoi les bibliothèques de lazy loading devraient être remplacées par l’attribut natif, ou configurées pour exclure les images situées au-dessus de la ligne de flottaison.
Quelles images différer, et lesquelles non
La règle générale est simple à énoncer : charger tout de suite ce qui est visible au premier coup d’œil, différer le reste. En pratique, la ligne de flottaison n’est pas une ligne fixe. Elle change avec l’appareil, avec l’orientation de l’écran, avec la présence de bandeaux ou d’avis sur les cookies, avec la longueur des titres. Une image qui se trouve sous la ligne de flottaison sur ordinateur peut être visible sur tablette, et inversement. Quelques critères aident à décider.
- Ne jamais différer l’élément LCP. La photo principale, la couverture, la première image produit : chargement immédiat et, pour la plus importante,
fetchpriority="high". - Ne pas différer les petites images au-dessus de la ligne de flottaison. Logo, icônes, avatars dans l’en-tête : elles pèsent peu et les différer n’apporte aucun bénéfice, alors que cela peut les faire apparaître tard.
- Différer tout ce qui est clairement plus bas. Galeries, images dans le corps d’un article après les premiers paragraphes, produits associés, logos de partenaires dans le pied de page, cartes et vidéos intégrées.
- Dans le doute, penser mobile. C’est là que se mesurent les Core Web Vitals les plus critiques, et c’est là que la ligne de flottaison est la plus haute : sur l’écran d’un smartphone, souvent seule la première image est visible.
Les grilles méritent de l’attention. Sur une page de catégorie avec quatre produits par ligne sur ordinateur et deux sur mobile, les images de la première ligne doivent être chargées tout de suite et les autres différées. Dans les carrousels, la première diapositive doit être traitée comme une image au-dessus de la ligne de flottaison ; les suivantes peuvent être différées, mais seulement si le carrousel ne les rend pas visibles automatiquement après quelques secondes.
Dimensions explicites : du lazy loading sans CLS
Une image différée arrive après que la page a déjà été affichée. Si le navigateur ne sait pas à l’avance quelle place elle occupera, à son arrivée elle décalera le contenu situé en dessous, générant du CLS. C’est pourquoi chaque image, différée ou non, doit avoir des attributs width et height, ou un aspect-ratio dans le CSS : le navigateur réserve la bonne place et l’image la remplit sans rien déplacer. Les images différées sont les plus exposées au problème, car elles arrivent quand l’utilisateur est déjà en train de lire ou de faire défiler la page.
Un placeholder, comme une couleur de fond assortie à l’image ou une version floutée très légère, améliore la perception pendant un défilement rapide, quand l’image n’a pas eu le temps d’arriver. Il doit toutefois occuper exactement la même place et ne pas nécessiter de JavaScript lourd pour fonctionner.
Au-delà des images : iframes, arrière-plans et rendu
Les iframes sont souvent les meilleures candidates au chargement différé, car une vidéo ou une carte intégrée entraîne avec elle des centaines de kilo-octets de JavaScript. loading="lazy" sur les iframes fonctionne dans tous les principaux navigateurs ; pour les vidéos, une façade qui n’affiche que l’aperçu et charge le lecteur au clic est encore plus efficace, comme nous l’avons vu en parlant des scripts tiers.
Les images d’arrière-plan définies en CSS ne prennent pas en charge l’attribut loading. Si elles sont au-dessus de la ligne de flottaison, elles demandent du soin, car le navigateur ne les découvre qu’après avoir lu le CSS : quand elles sont l’élément LCP, il vaut mieux les transformer en véritable élément img ou les précharger avec <link rel="preload">. Si elles sont sous la ligne de flottaison, on peut les affecter avec une classe appliquée par un Intersection Observer.
Il existe aussi une forme de report qui concerne le rendu plutôt que le téléchargement : la propriété CSS content-visibility: auto permet au navigateur de sauter le calcul de la mise en page et de l’affichage des sections hors écran jusqu’à ce qu’elles s’approchent. Sur des pages très longues et complexes, elle peut réduire le travail initial, mais il faut l’associer à contain-intrinsic-size pour éviter les sauts de la barre de défilement.
Combien on économise vraiment
Le bénéfice du chargement différé dépend de la longueur de la page et du comportement des utilisateurs. Sur un article de quinze images, dont la plupart des lecteurs ne voient que les trois ou quatre premières, l’économie peut dépasser un mégaoctet par visite : moins de données pour ceux qui naviguent avec un forfait limité, moins de bande passante utilisée pendant le chargement initial, moins de trafic sur le serveur ou le CDN. Sur une page courte avec deux images, le bénéfice est négligeable et le risque de choisir la mauvaise image à différer est proportionnellement plus élevé.
Il y a aussi un effet moins évident mais important : les images non visibles qui sont téléchargées tout de suite se disputent la bande passante avec les images visibles et les ressources critiques. Même si le navigateur leur donne une priorité basse, sur une connexion mobile limitée, dix téléchargements simultanés ralentissent celui qui compte. Les différer, c’est laisser la voie libre à l’image LCP, aux feuilles de style et aux polices.
Sur les pages à défilement infini, comme certaines listes de produits ou archives d’articles, le lazy loading est indispensable, mais il ne suffit pas : chaque nouveau bloc de contenu ajoute des éléments au DOM et du travail pour le navigateur. Au-delà d’une certaine taille, mieux vaut une pagination traditionnelle, qui offre en outre des adresses stables aux moteurs de recherche, ou un bouton explicite pour charger plus de résultats, qui laisse le contrôle à l’utilisateur et rend le comportement prévisible.
Comment WordPress se comporte
WordPress ajoute automatiquement loading="lazy" aux images de contenu à partir de la version 5.5 et aux iframes à partir de la 5.7. Dans les premières versions, il l’appliquait à toutes les images, y compris la première, avec pour résultat de dégrader le LCP de nombreux sites. Depuis la version 6.3, le comportement est plus intelligent : le cœur estime quelles images sont probablement au-dessus de la ligne de flottaison, ne les diffère pas et ajoute fetchpriority="high" à celle qu’il considère comme l’élément LCP.
L’estimation repose sur un seuil : par défaut, les trois premières images de contenu sont chargées sans report. La valeur peut être modifiée avec le filtre wp_omit_loading_attr_threshold, et cela vaut la peine quand on connaît la structure du thème. Sur les pages de ce site, par exemple, la seule image au-dessus de la ligne de flottaison dans les articles est la couverture, et le seuil est fixé à un : toutes les images du corps sont différées.
// Dans les articles, seule la couverture est au-dessus de la ligne de flottaison
add_filter(
'wp_omit_loading_attr_threshold',
function ( $threshold ) {
return is_singular( 'post' ) ? 1 : $threshold;
}
);
L’estimation du cœur fonctionne bien avec les thèmes qui utilisent les fonctions d’image standard, mais elle peut se tromper avec les page builders, les sliders et les blocs personnalisés qui génèrent le balisage à leur manière. S’y ajoutent les plugins d’optimisation qui appliquent leur propre lazy loading, souvent basé sur JavaScript, en chevauchement avec celui du cœur. Le résultat doit toujours être vérifié sur la page réelle : regarder dans le code source quelle image a fetchpriority="high", lesquelles ont loading="lazy", et le comparer avec l’élément LCP signalé par PageSpeed Insights.
Lazy loading et SEO
Le lazy loading natif ne crée pas de problème d’indexation : Googlebot voit l’attribut src et charge les images normalement. Le cas des solutions JavaScript qui ne chargent le contenu qu’en réaction au défilement est différent : le robot ne fait pas défiler la page comme un utilisateur, et un contenu qui n’apparaît qu’après un événement de défilement risque de ne pas être vu. Avec l’attribut natif, ou avec un Intersection Observer, le problème ne se pose pas.
Comment vérifier
Trois contrôles suffisent pour la plupart des sites. Dans PageSpeed Insights ou Lighthouse, vérifiez quel élément est le LCP et que l’avertissement signalant que l’image LCP est chargée en lazy loading n’apparaît pas. Dans le panneau Réseau des DevTools, rechargez la page sans la faire défiler et vérifiez que seules les images visibles sont téléchargées, plus celles situées dans la marge d’anticipation. Enfin, faites défiler rapidement sur une connexion lente simulée et regardez si les images apparaissent à temps et si le contenu reste immobile pendant leur arrivée.
En résumé
Le lazy loading est un outil efficace s’il est appliqué avec discernement : il réduit les données transférées et laisse de la bande passante aux ressources importantes, mais sur le mauvais élément, il retarde exactement ce que l’utilisateur doit voir en premier. La règle est de charger tout de suite ce qui est au-dessus de la ligne de flottaison, avec la priorité la plus haute pour l’élément LCP, et de différer tout le reste, toujours avec des dimensions explicites pour éviter les décalages de mise en page.
L’attribut natif loading a rendu presque toutes les bibliothèques JavaScript inutiles, et WordPress le gère automatiquement avec une estimation raisonnable des images situées au-dessus de la ligne de flottaison. Mais une estimation reste une estimation : connaître la structure de ses propres pages, ajuster le seuil et vérifier le résultat sur le terrain, c’est ce qui distingue le lazy loading qui accélère de celui qui, sans que personne s’en aperçoive, ralentit.