Technique
9 mai 2022

Intégrez une <iframe> proprement et dynamiquement

Bien que l'utilisation d'iframes ne soit plus conseillée à l'heure actuelle, celles-ci peuvent néanmoins s'avérer très pratiques pour insérer un contenu spécifique d'une autre page dans la page web actuelle. Cependant cette balise est assez capricieuse et ne s'ajuste pas automatiquement au contenu de votre page.

En utilisant la balise iframe, le contenu à l'intérieur de la balise est affiché avec une taille par défaut si la hauteur et la largeur ne sont pas spécifiées. Dans le cas contraire, si la hauteur et la largeur sont spécifiées, le contenu de la balise iframe aura donc une taille définie, mais celle-ci est fixe et ne s'adapte pas au conteneur parent. Le graal serait donc de pouvoir définir dynamiquement la taille de l'iframe lorsque son contenu est chargé sur la page Web. Et figurez-vous que j'ai la solution :)

Important : pour pouvoir resizer dynamiquement votre iframe, l'URL source de celle-ci doit se situer sur un domaine / site web qui vous appartient

Un problème de taille

Possédant une multitudes de sites web, j'ai souvent rencontré cette problématique : en intégrant une page B sur une page A sous forme d'iframe, le contenu n'était jamais adapté à la structure de ma page A. Par exemple si je souhaite intégrer un de mes autres articles de blog ici, je vais être confronté à cette même problématique de dimensions, car une iframe ne s'adapte pas nativement à la taille de son élément parent.

Par défaut

Avec dimensions fixes 500x500 sans scroll

On remarque ici que ni l'une ni l'autre n'est satisfaisante si l'on souhaite une intégration complète et totalement invisible sur notre page.

La solution

Il va falloir coder un peu de Javascript des 2 côtés pour obtenir le résultat optimal voulu. Une partie du code sera du côté de la source de votre iframe (pour mon exemple, sur l'article annexe), et l'autre partie sur la page actuelle.

Côté source de l'iframe

Concrètement, on va implémenter un intervalle appelant une fonction renvoyant la hauteur de l'iframe via une communication sécurisée inter-domaine postMessage. L'intervalle n'est pas obligatoire, mais permet de resizer correctement l'iframe au cas où certaines ressources mettent du temps à charger sur la page source :

// Size the parent iFrame
function iframeResize() {
    var height = $('body').outerHeight(); // IMPORTANT: If body's height is set to 100% with CSS this will not work.
    parent.postMessage("resize::"+height,"*");
}
  
$(document).ready(function() {
    // Resize iframe
    setInterval(iframeResize, 1000);
});


Côté page

On met en place un listener qui va écouter la valeur postée par le code implémenté précedemment, et on ajuste dynamiquement la hauteur de notre iframe :

// Listen for messages sent from the iFrame
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

eventer(messageEvent,function(e) {
  // If the message is a resize frame request
  if (e.data.indexOf('resize::') != -1) {
    var height = e.data.replace('resize::', '');
    document.getElementById('mon-iframe').style.height = height+'px';
  }
} ,false);


Résultat

On obtient une iframe propre au contenu parfaitement ajusté, responsive, et qui se fond dans le décor :)