Création de sites web en éco-conception

17/02/2020 Youlazy : un lecteur Youtube éco-conçu et accessible

Aujourd'hui nous allons éco-concevoir un lecteur vidéo Youtube à intégrer sur une page web.

Pourquoi ne pas utiliser le lecteur de base fourni par Youtube (un simple iframe) ? Parce qu'il engendre 14 requêtes vers les serveurs de Youtube, que la vidéo soit lue ou non.

Pour éviter ces requêtes inutiles, le développeur Arthur Corenzan a eu l'idée d'utiliser l'attribut srcdoc de l'iframe pour ne faire charger que la miniature, le lecteur complet (les 14 requêtes...) étant chargé au clic (en savoir plus (en anglais)).

Cette astuce réduit le nombre de requêtes à 1 (le chargement de la miniature). Mais c'est une requête de trop... Cette miniature, ne pourrait-on pas la charger de manière paresseuse (lazy loading) ? C'est ce que je vous propose de faire, grâce à un petit module JS que j'ai baptisé "Youlazy" (il reprend l'idée de l'attribut srcdoc susmentionnée).

Youlazy

Le chargement du lecteur vidéo va s'effectuer en plusieurs temps :

  1. Le HTML contient un lien pour regarder la vidéo sur le site de Youtube (on est à l'état "noscript").
  2. Aussitôt le JavaScript chargé, Youlazy transforme ce lien en un conteneur d'iframe (à ce stade, rien n'est téléchargé à partir de Youtube).

Utilisation par l'internaute :

  1. Le conteneur d'iframe apparaît à l'écran : Youlazy insère dans le conteneur un iframe qui charge alors la miniature (lazy loading)
  2. Au clic : chargement du player Youtube complet dans l'iframe

Le module JS Youlazy se compose de deux fonctions :

  • youlazy_init() pour créer le conteneur d'iframe
  • youlazy_load() pour y insérer l'iframe de la miniature (le lecteur complet sera chargé au clic)

Dans le code HTML

Le code HTML se résume donc à un simple lien pour regarder la vidéo sur Youtube. Par exemple :

Vidéo Youtube - L'accessibilité numérique à toutes les étapes d'un projet

stade 1.

Voilà le code HTML de base :

<a href="https://www.youtube.com/watch?v=y525BrxyvhA" target=_blank class=youlazy data-w=480 data-h=270 data-start=100>Vidéo Youtube - L'accessibilité numérique à toutes les étapes d'un projet</a>

Les attributs data-w et data-h contiennent respectivement les largeur et hauteur de la vidéo (cela permet d'en déduire le ratio).

Ces données sont disponibles via l'API de Youtube : https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=y525BrxyvhA&format=json

Quant à l'attribut optionnel data-start, il définit - en secondes - le moment où la vidéo doit commencer. À laisser vide pour que la vidéo commence au début.

La classe "youlazy" permet d'initialiser le plugin JS.

stade 2.

Aperçu du DOM après l'exécution de la fonction youlazy_init() :

<a href="javascript:void 0" target="_blank" class="youlazy init" data-w="480" data-h="270" data-id="y525BrxyvhA" data-title="Vidéo Youtube - L'accessibilité numérique à toutes les étapes d'un projet" > <div class="iframe-wrapper"></div> </a>

stade 3. (lazy loading)

À l'apparition à l'écran, un iframe est créé. Il ne contient pas le lecteur Youtube complet mais :

  • un lien pour charger le lecteur
  • la miniature (téléchargée à partir du site Youtube)
  • le bouton "play" (en SVG)

Ces éléments sont contenus dans l'attribut srcdoc. Précision : bien que l'iframe contienne un attribut src pour charger le lecteur complet, il n'en est rien, car lattribut srcdoc prend le pas.

Aperçu du DOM après l'exécution de la fonction youlazy_load() :

<a href="javascript:void 0" target="_blank" class="youlazy init loaded" data-w="480" data-h="270" data-id="y525BrxyvhA" data-title="Vidéo Youtube - L'accessibilité numérique à toutes les étapes d'un projet"> <div class="iframe-wrapper" style="padding-bottom: 56.25%;"> <iframe width="100%" height="100%" src="//www.youtube.com/embed/y525BrxyvhA" srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}svg{position:absolute;top:50%;left:50%;margin-top:-30px;margin-left:-30px;}span:hover path:first-child{fill:#Ff0000cc}</style><a href=//www.youtube.com/embed/y525BrxyvhA?autoplay=1><img src=https://img.youtube.com/vi/y525BrxyvhA/sddefault.jpg alt='Vidéo Youtube - L'accessibilité numérique à toutes les étapes d'un projet'><span><svg xmlns='http://www.w3.org/2000/svg' width=60 height=60 viewBox='0 -64 511 511'><path d='m256 384c-64-0-128-4-191-12-28-4-51-26-55-54-13-84-13-169 0-252 4-28 27-51 55-54 127-15 255-15 382 0 28 4 51 26 55 54 13 84 13 169 0 252-4 28-27 51-55 54-63 8-127 12-191 12zm0 0' fill='#000000cc'/><path d='M192 301V83.523l174.19 109zm0 0' fill='#fff'/></svg></span></a>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="1" title="Vidéo Youtube - L'accessibilité numérique à toutes les étapes d'un projet" ></iframe> </div> </a>

CSS

Code CSS obligatoire

.youlazy { display:block; } .youlazy .iframe-wrapper { position:relative; } .youlazy iframe { position:absolute; left:0; top:0; width:100%; height:100%; } .youlazy.init, .youlazy.init:hover, .youlazy.init:visited { border:0 !important; outline:0 !important; text-decoration:none !important; }

CSS pour personnaliser l'iframe

.youlazy { margin:20px auto; max-width:640px; } .youlazy .iframe-wrapper { max-height:400px; }

Ici, l'iframe ne dépassera pas 640x400

Code JS complet

/* * transforme le lien vers Youtube target=_blank en conteneur d'iframe */ function youlazy_init() {   if ('IntersectionObserver' in window) {     /* pour le Lazy loading */     var observer = new IntersectionObserver(         function (entries, observer) {           entries.forEach(function (entry) {             if (entry.isIntersecting) {               let a = entry.target;               youlazy_load(a);               observer.unobserve(entry.target);             }           });         }     );   }   // initialise chaque lien ayant la classe youlazy   document.querySelectorAll('.youlazy:not(.init)').forEach(function (el) {     // récupère le code Youtube de la vidéo     el.setAttribute('data-id', el.getAttribute('href').match(/=(.*)/)[1]);     // et son titre     el.setAttribute('data-title', el.textContent);     // désactive le lien     el.setAttribute('href', 'javascript:void 0');     // supprime le contenu du lien     el.innerHTML = '';     // crée le conteneur de l'iframe qui sera lazy-loadé     var iframe_wrapper = document.createElement("div");     iframe_wrapper.classList.add('iframe-wrapper');     el.appendChild(iframe_wrapper);     el.classList.add('init');     if ('IntersectionObserver' in window) {       observer.observe(el);     } else {       // fallback pour IE8 ; la miniature est chargée tout de suite       youlazy_load(el);     }   }); } /* * lazy loading d'un iframe ne contenant qu'une miniature */ function youlazy_load(el) {   var iframe_wrapper = el.querySelector('.iframe-wrapper');   var video_id = el.getAttribute('data-id');   var video_width = el.getAttribute('data-w');   var video_height = el.getAttribute('data-h');   var iframe_wrapper_width = iframe_wrapper.offsetWidth;   var iframe_wrapper_maxHeight = parseFloat(iframe_wrapper.style.maxHeight);   if (!isNaN(iframe_wrapper_maxHeight)) {     // si le conteneur de l'iframe a un max-height, la hauteur de l'iframe doit être limitée     var iframe_wrapper_height = iframe_wrapper_width * video_height / video_width;     if (iframe_wrapper_height > iframe_wrapper_maxHeight) {       iframe_wrapper_height = iframe_wrapper_maxHeight;       iframe_wrapper_width = iframe_wrapper_height * video_width / video_height;       el.style.width = iframe_wrapper_width + 'px';     }   }   // technique du padding-bottom en % pour que la ratio de la vidéo soit respecté quelle que soit la largeur du conteneur ; voir https://stackoverflow.com/questions/35814653/automatic-height-when-embedding-a-youtube-video     var padding_bottom = 100 * video_height / video_width;   iframe_wrapper.style.paddingBottom = padding_bottom + '%';   // format de la miniature le plus approprié (inutile de charger une image très large sur un petit écran   var format = 'default';   if (iframe_wrapper_width > 640) {     format = 'maxresdefault';   } else if (iframe_wrapper_width > 480) {     format = 'sddefault';   } else if (iframe_wrapper_width > 320) {     format = 'hqdefault';   } else if (iframe_wrapper_width > 120) {     format = 'mqdefault';   } else if (iframe_wrapper_width === 0) {     format = 'hqdefault';   }   // création de l'iframe et ajout dans le conteneur   // crédits : https://css-tricks.com/lazy-load-embedded-youtube-videos/   var iframe = document.createElement('iframe');   var attrs = {     width: "100%",     height: "100%",     src: "//www.youtube.com/embed/" + video_id,     srcdoc: "<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}svg{position:absolute;top:50%;left:50%;margin-top:-30px;margin-left:-30px;}span:hover path:first-child{fill:#Ff0000cc}</style><a href=//www.youtube.com/embed/" + video_id + "?autoplay=1><img src=https://img.youtube.com/vi/" + video_id + "/" + format + ".jpg alt=\'" + el.getAttribute('data-title') + "\'><span><svg xmlns='http://www.w3.org/2000/svg' width=60 height=60 viewBox='0 -64 511 511'><path d='m256 384c-64-0-128-4-191-12-28-4-51-26-55-54-13-84-13-169 0-252 4-28 27-51 55-54 127-15 255-15 382 0 28 4 51 26 55 54 13 84 13 169 0 252-4 28-27 51-55 54-63 8-127 12-191 12zm0 0' fill='#000000cc'/><path d='M192 301V83.523l174.19 109zm0 0' fill='#fff'/></svg></span></a>",     frameborder: "0",     allow: "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture",     allowfullscreen: "1",     title: el.getAttribute('data-title')   };   for (attr in attrs) {     iframe.setAttribute(attr, attrs[attr]);   }   iframe_wrapper.appendChild(iframe);   el.classList.add('loaded'); } youlazy_init();

Exemple

Vidéo Youtube - L'accessibilité numérique à toutes les étapes d'un projet

Tant que vous n'avez pas cliqué sur cette vidéo, seule la miniature a été téléchargée des serveurs de Youtube.

Commentaires

Ajouter un commentaire :