Le chargement différé des images avec Cloudinary

Le chargement différé des images avec Cloudinary

Cloudinary est premier sur le marché de la gestion des ressources numériques. L’entreprise propose un éventail varié de services allant de la fourniture d’images hautement optimisées au streaming de vidéos, en passant par une solution de gestion des ressources numériques. J’ai beaucoup travaillé avec Cloudinary au cours des dernières années, et je me suis vu offrir l’opportunité de devenir MDE (Media Developer Expert). Voici ma première production officielle en tant que MDE chez Cloudinary.

Dans cet article, je me concentre sur les techniques d’affichage différé des images optimisées et transformées grâce à l’API URL de Cloudinary. Cloudinary propose également des kits de développement côté client et côté serveur pour le traitement d’images. Par souci de simplicité, je m’en tiendrai à l’API URL.

Le chargement différé, pourquoi ?

L’importance du chargement différé s’accroît à mesure que le contenu des sites web s’enrichit. Je travaille sur des projets où les pages de produits sont essentiellement des histoires en images et vidéos, accompagnées d’un bouton d’achat. De manière générale, la qualité du débit mobile n’a pas suivi l’essor des contenus média sur les pages web. Par conséquent, nous devons prendre soin de nos chers utilisateurs en évitant de les surcharger avec des images inutiles. Evitez le chargement des images simultané au chargement de la page afin de réduire les requêtes http initiales, et assurez-vous de ne pas charger les images qui ne sont pas visibles à l’écran. Si, par exemple, vous avez un grand méga menu comportant beaucoup d’images, ne les chargez que lorsque l’utilisateur ouvre le menu, et de même pour les slideshows horizontaux et les carrousels.

Cloudinary ne fournit pas de méthode pour le chargement différé des assets, mais propose beaucoup d’autres choses auxquelles vous devriez vraiment jeter un coup d’œil si vous voulez fournir des images optimisées. Selon moi, Cloudinary apporte (entre autres) trois choses essentielles pour fournir des images optimisées de haute qualité :

  • Une optimisation de qualité intelligente (q_auto)
  • La sélection du format de fichier adapté à votre navigateur (f_auto)
  • Un rendu effectué avec le processus approprié (fl_progressive)

Je rajoute ces valeurs par défaut à chaque URL d’image Cloudinary. D’ailleurs, fl_progressive est une valeur par défaut. Cliquez sur les liens ci-dessus pour lire des articles plus détaillés sur ces fonctionnalités.

Ce que vous devez faire

La pire chose à faire, après avoir prévu des placeholders appropriés pour les images n’ayant pas encore été chargées (ce dont nous parlerons plus tard), est de ne pas prévoir l’espace dont aura besoin une image au chargement. Si vous ne gérez pas ça dans votre CSS, l’interface bougera au fur et à mesure que les images chargent et prennent leur place. Imaginez que vous avez pris le chargement différé en compte (et bravo pour ça !) mais que vous obteniez une mauvaise expérience au chargement de la page, avec une interface qui bouge dans tous les sens à cause du chargement des images. La seule chose que vous aurez obtenue, c’est un chargement initial de page qui se passe mal, et n’était-ce pas exactement ce que vous souhaitiez optimiser en implémentant le chargement différé des images ?

Ce que vous devez faire, c’est vous assurer que l’élément wrapper entourant votre image soit d’une taille appropriée à l’image une fois celle-ci chargée. Je sais que ce n’est pas chose facile, puisque vous ne connaissez généralement que le format de l’image, et pas sa taille exacte. Nous cherchons à développer des interfaces réactives, après tout.

Utilisez des pourcentages de padding en fonction de la largeur de l’image afin de réserver l’espace nécessaire selon le format d’image. Si la largeur de votre élément est de 200 px avec un padding-top de 100%, le padding-top aura une valeur de 200 px. C’est un format 1:1. Si vous forcez la hauteur de l’élément à zéro, le padding sera alors le seul élément du modèle de boîte affectant la hauteur. Si vous utilisez un padding de 56.25%, vous obtiendrez un format 16:9 (9 / 16 = 0.5625). Génial, non ?

Pour cela, la meilleure technique est d’utiliser un élément :pseudo. Rajoutez ce mixin au wrapper autour de votre balise image.

@mixin aspect-ratio($width, $height) {
  &:before { content:''; float: left; padding-bottom: percentage($height/$width); }
  &:after { content:''; display: table; clear: both; }
}

Si vous n’aimez pas SCSS, vous pouvez aussi faire des trucs à la mode comme ça (remarquez que je n’utilise pas :after dans cet exemple. CSS est flexible).

<div class="image-wrapper" style="--aspect-ratio:16/9;">
  <img 
    src="https://res.cloudinary.com/timbenniks/image/upload/q_auto,f_auto/hi.jpg" 
    alt="A dude saying hi"
  />
</div>
[style*="--aspect-ratio"] > :first-child { width: 100%; }
[style*="--aspect-ratio"] > img { height: auto; }

@supports (--custom:property) {
  [style*="--aspect-ratio"] { position: relative; }
    
  [style*="--aspect-ratio"]::before {
    content: "";
    display: block;
    padding-bottom: calc(100% / (var(--aspect-ratio)));
  }
    
  [style*="--aspect-ratio"] > :first-child {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
  }  
}

Vous devez également insérer une balise <noscript> contenant une image de repli pour les utilisateurs n’ayant pas JS et pour les robots d’indexation. Je sais que Google décrypte le JS, mais à l’heure où j’écris ceci le décryptage n’est fait que lorsqu’ils en ont les ressources et lors de la deuxième exploration de votre page. Si vous avez des images avec des balises alternatives dans votre DOM, Google les indexera au premier aller-retour.

Types de balises d’image

Il y a plusieurs façons d’insérer une image. Si vous avez simplement besoin d’afficher une image sans la redimensionner à des fins d’adaptabilité, utilisez une bonne vieille balise image.

Les URLs Cloudinary sont raccourcies dans ces exemples afin de faciliter la lecture.

<img
  src="https://res.cloudinary.com/timbenniks/hi.jpg"
  alt="A dude saying hi"
/>

Si l’adaptabilité est importante, utilisez <img /> avec srcset et sizes.

<img 
  src="https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_320/hi.jpg" 
  alt="A dude saying hi" 
  sizes="100vw"
  srcset="https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_320/hi.jpg 320w, 
          https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_600/hi.jpg 600w, 
          https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_850/hi.jpg 850w"
/>

Enfin, si vous avez besoin de plusieurs sources d’image par requête média, vous pouvez utiliser la balise <picture>. Assurez-vous de placer la source d’image la plus lourde en premier.

<picture>
  <source 
    media="(min-width: 650px)"
    sizes="50vw"
    srcset="https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_640/hi.jpg 650w, 
            https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_700/hi.jpg 700w, 
            https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_850/hi.jpg 850w"
  />
  <source 
    media="(min-width: 400px)"
    sizes="80vw"
    srcset="https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_300/wut.jpg 300, 
            https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_350/wut.jpg 350w, 
            https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_400/wut.jpg 400w"
  />
  <img 
    src="https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_320/small.jpg" 
    alt="A dude saying hi" 
    sizes="100vw"
    srcset="https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_150/small.jpg 150w, 
            https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_250/small.jpg 250w, 
            https://res.cloudinary.com/timbenniks/q_auto,f_auto,w_400/small.jpg 400w"
  />
</picture>

Je n’ai pas mentionné les images de fond ici par souci de simplicité.

Options de placeholders

Vous avez accès à tout un tas d’options permettant d’indiquer que de jolies images bien nettes vont s’afficher. Vous pouvez ne rien faire, ce qui entraîne un vide dans votre page qui se remplit au fur et à mesure que l’image charge. C’est une solution viable, qui a l’avantage de ne pas demander beaucoup de travail.

Si cette approche vous plaît, je vous suggérerais d’aller un peu plus loin en rajoutant une image de fond avec juste assez de contraste pour indiquer à l’utilisateur qu’il s’agit d’un placeholder. Certains sites utilisent en placeholder un dégradé basé sur les couleurs présentes dans l’image. Vous pouvez aussi y ajouter votre logo, ou un chargeur animé avec un peu de magie CSS.

Pour vous assurer que certains navigateurs n’affichent pas l’erreur d’image introuvable, utilisez un GIF transparent de 1 px dans l’attribut src.

<img 
  src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="
  alt="Some image" />

Il existe d’autres alternatives un peu plus délicates à mettre en place, qui rajoutent un petit côté « à la mode » à l’insertion. Jetez un coup d’œil à cette idée géniale de placeholder SVG, qui existe depuis 2017.

Vous pouvez aussi utiliser la technique du « dégradé de flou ». Dans cet exemple, l’image initiale chargée en tant que placeholder est une version floue, basse résolution de l’image originale. Dès que l’image originale est chargée, elle remplace la version floue avec un bel effet de dégradé. Pour rendre le flou plus convaincant, vous pouvez aussi l’ajouter avec un filtre CSS.

Cette technique crée une expérience agréable à l’œil, mais a l’inconvénient de faire deux appels http pour une seule image. Dans nos projets, nous avons tendance à accompagner le chargement des dégradés de packshots et des assets supplémentaires par un placeholder de couleur subtile. Choisissez vos armes avec soin.

Examinons un ensemble de ces techniques rassemblées dans un bel exemple de bac à sable. Notez que Cloudinary est extrêmement rapide. Pour voir ces techniques en action, utilisez la fonction throttle dans le panneau d’outils de développement du navigateur de votre choix.

Note supplémentaire : codesandbox.io utilise le style que j’ai ajouté à l’événement document ready. En utilisant la fonction throttle, vous pouvez voir très clairement que SSR aurait été ici une excellente option. Je parlerai davantage de l’accessibilité des connexions lentes et de la façon de les gérer avec élégance dans un prochain article.

En dernier lieu, ce code est conçu à titre d’exemple afin de vous aider à appréhender la création d’images à chargement différé. Pour une utilisation à des fins de production, je conseillerais plutôt quelque chose de l’ordre de Lozad.js ou lazyload.js.

 

Article orginal : https://timbenniks.nl/writings/lazy-loading-images-with-cloudinary/

Article traduit par Valtech.