rendre la hauteur iframe dynamique en fonction du contenu à l'intérieur - JQUERY / Javascript

202

Je charge une page Web aspx dans un iframe. Le contenu de l'Iframe peut être plus haut que la hauteur de l'Iframe. L'iframe ne doit pas avoir de barres de défilement.

J'ai une divbalise wrapper à l'intérieur de l'iframe qui est essentiellement tout le contenu. J'ai écrit quelques jQuery pour que le redimensionnement se produise:

$("#TB_window", window.parent.document).height($("body").height() + 50);

TB_windowest le div dans lequel il Iframeest contenu.

body - la balise body de l'aspx dans l'iframe.

Ce script est attaché au contenu iframe. J'obtiens l' TB_windowélément de la page parent. Bien que cela fonctionne bien sur Chrome, mais TB_window s'effondre dans Firefox. Je suis vraiment confus / perdu sur pourquoi cela se produit.

karry
la source
cette page .aspx iframe provient du même nom de domaine?
AlexC
pouvez-vous vérifier que $ ("body"). height () a une valeur dans firefox?
Michael L Watson
yes..the iframe est dans le même domaine que la page de conteneur
karry
@MichaelLWatson On dirait que la fenêtre de surveillance de Firebug a la valeur 0 pour la hauteur du corps ... Chrome a
quand
Exemple de hauteur auto angulaire iFrame: gitlab.com/reduardo7/angular-iframe-auto-height
Eduardo Cuomo

Réponses:

212

Vous pouvez récupérer la hauteur du IFRAME contenu de en utilisant: contentWindow.document.body.scrollHeight

Une fois le IFRAMEfichier chargé, vous pouvez modifier la hauteur en procédant comme suit:

<script type="text/javascript">
  function iframeLoaded() {
      var iFrameID = document.getElementById('idIframe');
      if(iFrameID) {
            // here you can make the height, I delete it first, then I make it again
            iFrameID.height = "";
            iFrameID.height = iFrameID.contentWindow.document.body.scrollHeight + "px";
      }   
  }
</script>   

Ensuite, sur la IFRAMEbalise, vous connectez le gestionnaire comme ceci:

<iframe id="idIframe" onload="iframeLoaded()" ...

Il y a quelque temps, j'ai eu une situation où j'avais également besoin d'appeler iframeLoadedde IFRAMElui - même après qu'une soumission de formulaire eut eu lieu à l'intérieur. Vous pouvez accomplir cela en procédant comme suit dans les IFRAMEscripts de contenu de:

parent.iframeLoaded();
Aristos
la source
153
Il ne prend pas en charge sur plusieurs domaines.
Soumya
3
@Soumya Le domaine croisé n'a rien à voir avec ce code. Il y a un problème de sécurité que vous contournez avec une commande.
Aristos
9
@Soumya Recherchez le X-FRAME-OPTIONSpour ajouter une ligne comme: Response.AddHeader("X-FRAME-OPTIONS", "SAMEORIGIN");ouresponse.addHeader("X-FRAME-OPTIONS", "Allow-From https://some.othersite.com");
Aristos
15
Cela résout le problème de dimensionnement de l'iframe interdomaine github.com/davidjbradshaw/iframe-resizer
David Bradshaw
2
@deebs Vous pouvez également essayer de passer iFrameID.height = "";à iFrameID.height = "20px";. La hauteur par défaut de l'iframe du navigateur est de 150 pixels, ce qui la ""réinitialise.
philfreo
112

Une réponse légèrement améliorée à Aristos ...

<script type="text/javascript">
  function resizeIframe(iframe) {
    iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
  }
</script>  

Déclarez ensuite dans votre iframe comme suit:

<iframe onload="resizeIframe(this)" ...

Il y a deux améliorations mineures:

  1. Vous n'avez pas besoin d'obtenir l'élément via document.getElementById - car vous l'avez déjà dans le rappel onload.
  2. Il n'est pas nécessaire de définir le iframe.height = ""si vous allez le réaffecter dans la toute prochaine instruction. Cela entraîne en fait une surcharge lorsque vous traitez avec un élément DOM.

Modifier: si le contenu du cadre change constamment, appelez:

parent.resizeIframe(this.frameElement); 

depuis l'iframe après la mise à jour. Fonctionne pour la même origine.

Ou pour détecter automatiquement:

  // on resize
  this.container = this.frameElement.contentWindow.document.body;

  this.watch = () => {
    cancelAnimationFrame(this.watcher);

    if (this.lastScrollHeight !== container.scrollHeight) {
      parent.resizeIframeToContentSize(this.frameElement);  
    }
    this.lastScrollHeight = container.scrollHeight;
    this.watcher = requestAnimationFrame(this.watch);
  };
  this.watcher = window.requestAnimationFrame(this.watch);
BlueFish
la source
6
Que feriez-vous si le contenu du cadre change constamment?
Kevin
Si la taille du contenu ne cesse de changer et / ou si votre iframe est conçu pour se trouver sur d'autres domaines que le domaine d'où l'iframe extrait la page, vous devrez faire quelque chose de différent.
BlueFish
4
Pour cela ... la solution est d'utiliser postMessage et receiveMessage. J'ai résolu cela en utilisant github.com/jeffomatic/nojquery-postmessage
BlueFish
L'idée est de calculer la nouvelle hauteur et d'envoyer un message au cadre parent qui doit recevoir le message et d'ajuster la hauteur de l'iframe en conséquence.
BlueFish
Il y avait toujours quelques pixels courts pour moi, alors j'ai trouvé ceci: function resizeIframe(iframe) { var size=iframe.contentWindow.document.body.scrollHeight; var size_new=size+20; iframe.height = size_new + "px"; }
Martin Mühl
56

J'ai trouvé que la réponse acceptée ne suffisait pas, car X-FRAME-OPTIONS: Allow-From n'est pas pris en charge dans Safari ou Chrome . Je suis allé avec une approche différente à la place, trouvée dans une présentation donnée par Ben Vinegar de Disqus. L'idée est d'ajouter un écouteur d'événement à la fenêtre parent, puis à l'intérieur de l'iframe, utilisez window.postMessage pour envoyer un événement au parent lui disant de faire quelque chose (redimensionner l'iframe).

Donc, dans le document parent, ajoutez un écouteur d'événement:

window.addEventListener('message', function(e) {
  var $iframe = jQuery("#myIframe");
  var eventName = e.data[0];
  var data = e.data[1];
  switch(eventName) {
    case 'setHeight':
      $iframe.height(data);
      break;
  }
}, false);

Et à l'intérieur de l'iframe, écrivez une fonction pour publier le message:

function resize() {
  var height = document.getElementsByTagName("html")[0].scrollHeight;
  window.parent.postMessage(["setHeight", height], "*"); 
}

Enfin, à l'intérieur de l'iframe, ajoutez un onLoad à la balise body pour déclencher la fonction de redimensionnement:

<body onLoad="resize();">
Marty Mulligan
la source
1
Pour que cela fonctionne pour moi, j'ai dû changer "window.parent" en "parent".
prograhammer
Génial! mais il ne charge la hauteur qu'une seule fois. Si vous voulez rendre l'iframe vraiment réactif, je préfère appeler la méthode de redimensionnement à chaque seconde, comme ceci:setInterval(resize, 1000);
Jules Colle
12

Ajoutez ceci à l'iframe, cela a fonctionné pour moi:

onload="this.height=this.contentWindow.document.body.scrollHeight;"

Et si vous utilisez jQuery essayez ce code:

onload="$(this).height($(this.contentWindow.document.body).find(\'div\').first().height());"
Mohit Aneja
la source
6

Il existe quatre propriétés différentes que vous pouvez consulter pour obtenir la hauteur du contenu dans un iFrame.

document.documentElement.scrollHeight
document.documentElement.offsetHeight
document.body.scrollHeight
document.body.offsetHeight

Malheureusement, ils peuvent tous donner des réponses différentes et celles-ci ne sont pas cohérentes entre les navigateurs. Si vous définissez la marge corporelle sur 0, le document.body.offsetHeightdonne la meilleure réponse. Pour obtenir la valeur correcte, essayez cette fonction; qui provient de la bibliothèque iframe-resizer qui veille également à conserver la taille correcte de l'iFrame lorsque le contenu change ou que le navigateur est redimensionné.

function getIFrameHeight(){
    function getComputedBodyStyle(prop) {
        function getPixelValue(value) {
            var PIXEL = /^\d+(px)?$/i;

            if (PIXEL.test(value)) {
                return parseInt(value,base);
            }

            var 
                style = el.style.left,
                runtimeStyle = el.runtimeStyle.left;

            el.runtimeStyle.left = el.currentStyle.left;
            el.style.left = value || 0;
            value = el.style.pixelLeft;
            el.style.left = style;
            el.runtimeStyle.left = runtimeStyle;

            return value;
        }

        var 
            el = document.body,
            retVal = 0;

        if (document.defaultView && document.defaultView.getComputedStyle) {
            retVal =  document.defaultView.getComputedStyle(el, null)[prop];
        } else {//IE8 & below
            retVal =  getPixelValue(el.currentStyle[prop]);
        } 

        return parseInt(retVal,10);
    }

    return document.body.offsetHeight +
        getComputedBodyStyle('marginTop') +
        getComputedBodyStyle('marginBottom');
}
David Bradshaw
la source
Cela ne fonctionne pas avec les éléments qui «roulent», par exemple les tables de données ou les div flottants. La hauteur est basée sur la hauteur normale non déroulée et non sur la hauteur finale.
djack109
@ djack109 probablement quelque chose dans votre CSS arrête un élément rétrécissant sur votre page
David Bradshaw
3

Les autres réponses ne fonctionnaient pas pour moi, j'ai donc fait quelques changements. J'espère que cela vous aidera

$('#iframe').on("load", function() {
    var iframe = $(window.top.document).find("#iframe");
    iframe.height(iframe[0].ownerDocument.body.scrollHeight+'px' );
});
Ravi
la source
2

Plutôt que d'utiliser javscript / jquery, le moyen le plus simple que j'ai trouvé est:

<iframe style="min-height:98vh" src="http://yourdomain.com" width="100%"></iframe>

Ici 1vh = 1% de la hauteur de la fenêtre du navigateur. La valeur théorique de la hauteur à régler est donc 100vh mais pratiquement 98vh a fait la magie.

Binod
la source
9
Cela ne tient pas compte de la hauteur du contenu de l'iframe.
Adrian Pauly
Cela se rapproche suffisamment lorsque vous n'avez pas de moyen simple de contourner les drames
interdomaines
2

Juste au cas où cela aiderait quelqu'un. J'arrachais mes cheveux en essayant de faire fonctionner cela, puis j'ai remarqué que l'iframe avait une entrée de classe avec une hauteur: 100%. Lorsque j'ai supprimé cela, tout a fonctionné comme prévu. Veuillez donc vérifier les conflits CSS.

user8640976
la source
2

vous pouvez également ajouter un requestAnimationFrame répétitif à votre resizeIframe (par exemple à partir de la réponse de @ BlueFish) qui sera toujours appelé avant que le navigateur ne peint la mise en page et vous pouvez mettre à jour la hauteur de l'iframe lorsque son contenu a changé de hauteur. par exemple, formulaires de saisie, contenu chargé paresseux, etc.

<script type="text/javascript">
  function resizeIframe(iframe) {
    iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
    window.requestAnimationFrame(() => resizeIframe(iframe));
  }
</script>  

<iframe onload="resizeIframe(this)" ...

votre rappel devrait être assez rapide pour n'avoir aucun impact important sur vos performances globales

user2520818
la source
1
il s'agit d'une solution très simple qui, dès les premiers tests, fonctionne très bien. Je serais intéressé par les implications de performance de l'utilisation de ceci.
KFE
Je viens de croiser un cas Uncaught TypeError: Cannot read property 'scrollHeight' of nulldepuis bodyest null, mais il travaille habituellement.
caot
1

Vous pouvez vous référer à la question connexe ici - Comment faire la largeur et la hauteur de iframe même que sa div parent?

Pour définir la hauteur dynamique -

  1. Nous devons communiquer avec les iFrames interdomaines et le parent
  2. Ensuite, nous pouvons envoyer la hauteur de défilement / la hauteur du contenu de l'iframe à la fenêtre parente

Et les codes - https://gist.github.com/mohandere/a2e67971858ee2c3999d62e3843889a8

Mohan Dere
la source
1

J'utilise jQuery et le code ci-dessous fonctionne pour moi,

var iframe = $(window.top.document).find("#iframe_id_here");
iframe.height(iframe.contents().height()+'px' );
srijishks
la source
0

J'ai trouvé que la réponse de Troy ne fonctionnait pas. C'est le même code retravaillé pour ajax:

$.ajax({                                      
    url: 'data.php',    
    dataType: 'json',                             

    success: function(data)
    {
        // Put the data onto the page

        // Resize the iframe
        var iframe = $(window.top.document).find("#iframe");
        iframe.height( iframe[0].contentDocument.body.scrollHeight+'px' );
    }
});
Martin Lester
la source
0

Pour ajouter au morceau de fenêtre qui semble se couper en bas, surtout lorsque vous n'avez pas de défilement, j'ai utilisé:

function resizeIframe(iframe) {
    var addHeight = 20; //or whatever size is being cut off
    iframe.height = iframe.contentWindow.document.body.scrollHeight + addHeight + "px";
  }
Matt Stacey
la source
0

Celui-ci est utile lorsque vous avez besoin d'une solution sans jquery. Dans ce cas, vous devriez essayer d'ajouter un conteneur et de lui définir un remplissage en pourcentages

Exemple de code HTML:

<div class="iframecontainer">
    <iframe scrolling="no" src="..." class="iframeclass"width="999px" height="618px"></iframe>
</div>

Exemple de code CSS:

.iframeclass{
    position: absolute;
    top: 0;
    width: 100%;
}

.iframecontainer{
    position: relative;
    width: 100%;
    height: auto;
    padding-top: 61%;
}
Juan M
la source
0

La solution simple consiste à mesurer la largeur et la hauteur de la zone de contenu, puis à utiliser ces mesures pour calculer le pourcentage de remplissage inférieur.

Dans ce cas, les mesures sont 1680 x 720 px, donc le rembourrage en bas est 720/1680 = 0,43 * 100, ce qui revient à 43%.

.canvas-container {    
    position: relative;
    padding-bottom: 43%; // (720 ÷ 1680 = 0.4286 = 43%)
    height: 0;
    overflow: hidden;   
}

.canvas-container iframe {    
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;   
}
loek
la source
0

Une réponse légèrement améliorée à BlueFish ...

function resizeIframe(iframe) {
    var padding = 50;
    if (iframe.contentWindow.document.body.scrollHeight < (window.innerHeight - padding))
        iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
    else
        iframe.height = (window.innerHeight - padding) + "px";
}

Cela prend en compte la hauteur de l'écran Windows (navigateur, téléphone), ce qui est bon pour la conception réactive et les iframes qui ont une hauteur énorme. Le rembourrage représente le rembourrage que vous souhaitez au-dessus et en dessous de l'iframe dans le cas où il passe par tout l'écran.

Tadej Vengust
la source
0
jQuery('.home_vidio_img1 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery(this).replaceWith(video);
});

jQuery('.home_vidio_img2 img').click(function(){
    video = <iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>;
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});

jQuery('.home_vidio_img3 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});

jQuery('.home_vidio_img4 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});
Keyur Savsani
la source
0

Exemple d'utilisation de PHP htmlspecialchars () + vérifier si la hauteur existe et est> 0:

$my_html_markup = ''; // Insert here HTML markup with CSS, JS... '<html><head></head><body>...</body></html>'
$iframe = '<iframe onload="if(this.contentWindow.document.body.scrollHeight) {this.height = this.contentWindow.document.body.scrollHeight;}" width="100%" src="javascript: \''. htmlspecialchars($my_html_markup) . '\'"></iframe>';
jteks
la source
0

il suffit de faire la position du conteneur iframe: absolu et iframe changera automatiquement sa hauteur en fonction de son contenu

<style>
   .iframe-container {
       display: block;
       position: absolute;
       /*change position as you need*/
       bottom: 0;
       left: 0;
       right: 0;
       top: 0;
   }
   iframe {
       margin: 0;
       padding: 0;
       border: 0;
       width: 100%;
       background-color: #fff;
   }
 </style>
 <div class="iframe-container">
     <iframe src="http://iframesourcepage"></iframe>
 </div>
Hatem Badawi
la source
-1
$(document).height() // - $('body').offset().top

et / ou

$(window).height()

Voir la question Débordement de pile Comment obtenir la hauteur d'un élément de corps .

Essayez ceci pour trouver la hauteur du corps dans jQuery:

if $("body").height()

Il n'a pas de valeur si Firebug . C'est peut-être le problème.

Michael L Watson
la source
J'ai essayé de faire les deux ... ça arrive toujours sur Firefox. firefox n'obtient pas en quelque sorte le window.height () sur l'iframe. Comme je l'ai mentionné, le script est attaché au contenu Iframe et je l'appelle dans la fonction document.ready ()
karry