Machen Sie die Höhe des Iframes basierend auf dem Inhalt in JQUERY / Javascript dynamisch

202

Ich lade eine Aspx-Webseite in einen Iframe. Der Inhalt im Iframe kann höher sein als die Höhe des Iframes. Der Iframe sollte keine Bildlaufleisten haben.

Ich habe ein Wrapper- divTag im Iframe, das im Grunde den gesamten Inhalt enthält. Ich habe jQuery geschrieben, um die Größenänderung zu ermöglichen:

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

Wo TB_windowist das Div, in dem das Iframeenthalten ist?

body - das Body-Tag des Aspx im Iframe.

Dieses Skript ist an den Iframe-Inhalt angehängt. Ich erhalte das TB_windowElement von der übergeordneten Seite. Dies funktioniert zwar gut in Chrome, aber das TB_window bricht in Firefox zusammen. Ich bin wirklich verwirrt / verloren darüber, warum das passiert.

Karry
quelle
Diese .aspx-Iframe-Seite stammt aus demselben Domainnamen?
AlexC
Können Sie $ ("body") überprüfen. height () hat einen Wert in Firefox?
Michael L Watson
Ja ... der Iframe befindet sich in derselben Domain wie die Containerseite
Karry
@ MichaelLWatson Es sieht so aus, als hätte Firebug Watch Window den Wert 0 für die Körpergröße ... Chrome hat allerdings einen Wert
Karry
Angular iFrame Auto-Height Beispiel: gitlab.com/reduardo7/angular-iframe-auto-height
Eduardo Cuomo

Antworten:

211

Sie können die Höhe des IFRAMEInhalts abrufen, indem Sie Folgendes verwenden: contentWindow.document.body.scrollHeight

Nachdem das IFRAMEgeladen wurde, können Sie die Höhe wie folgt ändern:

<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>   

Dann schließen Sie auf dem IFRAMETag den Handler wie folgt an:

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

Ich hatte vor einiger Zeit eine Situation, in der ich zusätzlich iframeLoadedvon IFRAMEselbst anrufen musste, nachdem ein Formular eingereicht wurde. Sie können dies erreichen, indem Sie in den IFRAMEInhaltsskripten des Skripts Folgendes ausführen:

parent.iframeLoaded();
Aristos
quelle
152
Cross Domain wird nicht unterstützt.
Soumya
3
@ Soumya Die Cross Domain hat nichts mit diesem Code zu tun. Es gibt ein Sicherheitsproblem, das Sie mit einem Befehl umgehen.
Aristos
9
@ Soumya Suchen Sie nach dem X-FRAME-OPTIONS, um eine Zeile hinzuzufügen als: Response.AddHeader("X-FRAME-OPTIONS", "SAMEORIGIN");oderresponse.addHeader("X-FRAME-OPTIONS", "Allow-From https://some.othersite.com");
Aristos
15
Dies löst das domänenübergreifende Iframe-Größenproblem github.com/davidjbradshaw/iframe-resizer
David Bradshaw
2
@deebs Sie könnten auch versuchen zu ändern iFrameID.height = "";auf iFrameID.height = "20px";. Die Standard-Iframe-Höhe des Browsers beträgt 150px, wodurch ""sie zurückgesetzt wird.
Philfreo
112

Eine leicht verbesserte Antwort auf Aristos ...

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

Dann deklarieren Sie in Ihrem Iframe wie folgt:

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

Es gibt zwei kleinere Verbesserungen:

  1. Sie müssen das Element nicht über document.getElementById abrufen, da Sie es bereits im Onload-Rückruf haben.
  2. Sie müssen das nicht festlegen, iframe.height = ""wenn Sie es in der nächsten Anweisung neu zuweisen möchten. Dies verursacht tatsächlich einen Overhead, wenn Sie mit einem DOM-Element arbeiten.

Bearbeiten: Wenn sich der Inhalt im Frame ständig ändert, rufen Sie auf:

parent.resizeIframe(this.frameElement); 

aus dem iframe nach dem Update. Funktioniert für den gleichen Ursprung.

Oder um automatisch zu erkennen:

  // 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);
Blaufisch
quelle
6
Was würden Sie tun, wenn sich der Inhalt im Frame ständig ändert?
Kevin
Wenn sich die Inhaltsgröße ständig ändert und / oder wenn Ihr Iframe für andere Domänen als die Domäne ausgelegt ist, aus der der Iframe die Seite abruft, müssen Sie etwas anderes tun.
BlueFish
4
Dafür ... besteht die Lösung darin, postMessage und receiveMessage zu verwenden. Ich habe dies mit github.com/jeffomatic/nojquery-postmessage
BlueFish
Die Idee ist, die neue Höhe zu berechnen und eine Nachricht an den übergeordneten Frame zu senden, der die Nachricht empfangen und die Höhe des Iframes entsprechend anpassen muss.
BlueFish
Es war immer ein paar Pixel kurz für mich, also kam ich function resizeIframe(iframe) { var size=iframe.contentWindow.document.body.scrollHeight; var size_new=size+20; iframe.height = size_new + "px"; }
Martin Mühl
56

Ich fand, dass die akzeptierte Antwort nicht ausreichte, da X-FRAME-OPTIONS: Allow-From in Safari oder Chrome nicht unterstützt wird . Ging stattdessen mit einem anderen Ansatz, gefunden in einer Präsentation von Ben Vinegar von Disqus. Die Idee ist, dem übergeordneten Fenster einen Ereignis-Listener hinzuzufügen und dann innerhalb des Iframes mit window.postMessage ein Ereignis an das übergeordnete Fenster zu senden, das ihn auffordert, etwas zu tun (Größe des Iframes ändern).

Fügen Sie im übergeordneten Dokument einen Ereignis-Listener hinzu:

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);

Und schreiben Sie im Iframe eine Funktion, um die Nachricht zu posten:

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

Fügen Sie schließlich im iframe ein onLoad zum body-Tag hinzu, um die Größenänderungsfunktion auszulösen:

<body onLoad="resize();">
Marty Mulligan
quelle
1
Damit dies für mich funktioniert, musste ich "window.parent" in "parent" ändern.
Programmierer
Toll! Die Höhe wird jedoch nur einmal geladen. Wenn Sie den Iframe wirklich reaktionsschnell machen möchten, rufe ich die Größenänderungsmethode lieber jede Sekunde auf, wie folgt:setInterval(resize, 1000);
Jules Colle
12

Fügen Sie dies dem Iframe hinzu, dies hat bei mir funktioniert:

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

Und wenn Sie jQuery verwenden, versuchen Sie diesen Code:

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

Es gibt vier verschiedene Eigenschaften, mit denen Sie die Höhe des Inhalts in einem iFrame ermitteln können.

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

Leider können sie alle unterschiedliche Antworten geben und diese sind zwischen den Browsern inkonsistent. Wenn Sie den Körperrand auf 0 setzen, document.body.offsetHeightgibt das die beste Antwort. Versuchen Sie diese Funktion, um den richtigen Wert zu erhalten. Dies wird aus der iframe-resizer- Bibliothek entnommen , die auch darauf achtet, dass der iFrame die richtige Größe beibehält, wenn sich der Inhalt ändert oder die Größe des Browsers geändert wird.

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
quelle
Dies funktioniert nicht mit Elementen, die "aufrollen", z. B. Datentabellen oder schwebende Divs. Die Höhe basiert auf der normalen aufgerollten Höhe und nicht auf der endgültigen Höhe.
djack109
@ djack109 höchstwahrscheinlich stoppt etwas in Ihrem CSS ein Element, das auf Ihrer Seite schrumpft
David Bradshaw
3

Anstatt Javscript / JQuery zu verwenden, fand ich am einfachsten:

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

Hier ist 1vh = 1% der Browserfensterhöhe. Der theoretische Wert der einzustellenden Höhe ist also 100vh, aber praktisch 98vh hat die Magie bewirkt.

Binod
quelle
8
Dies berücksichtigt nicht die Inhaltshöhe des Iframes.
Adrian Pauly
Dies kommt nahe genug, wenn Sie keine einfache Möglichkeit haben, domänenübergreifendes Drama zu
umgehen
3

Andere Antworten haben bei mir nicht funktioniert, deshalb habe ich einige Änderungen vorgenommen. Hoffe das wird helfen

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

Nur für den Fall, dass dies jemandem hilft. Ich zog mir die Haare aus, um dies zum Laufen zu bringen, und bemerkte dann, dass der Iframe einen Klasseneintrag mit einer Höhe von 100% hatte. Als ich das entfernte, funktionierte alles wie erwartet. Bitte überprüfen Sie, ob CSS-Konflikte vorliegen.

user8640976
quelle
2

Sie können Ihrem resizeIframe auch einen sich wiederholenden requestAnimationFrame hinzufügen (z. B. aus der Antwort von @ BlueFish), der immer aufgerufen wird, bevor der Browser das Layout malt, und Sie können die Höhe des iframes aktualisieren, wenn dessen Inhalt seine Höhe geändert hat. zB Eingabeformulare, träge geladene Inhalte usw.

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

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

Ihr Rückruf sollte schnell genug sein, um keinen großen Einfluss auf Ihre Gesamtleistung zu haben

user2520818
quelle
1
Dies ist eine sehr raffinierte Lösung, die nach ersten Tests sehr gut funktioniert. Ich würde mich für die Auswirkungen dieser Verwendung auf die Leistung interessieren.
KFE
Gerade lief Fall in Uncaught TypeError: Cannot read property 'scrollHeight' of nullda bodyist null, aber es funktioniert in der Regel.
Caot
1

Ich verwende jQuery und den folgenden Code, der für mich funktioniert.

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

Ich fand, dass die Antwort von Troy nicht funktionierte. Dies ist derselbe Code, der für Ajax überarbeitet wurde:

$.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
quelle
0

Um den Fensterblock zu erweitern, der unten abgeschnitten zu sein scheint, insbesondere wenn Sie nicht scrollen, habe ich Folgendes verwendet:

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

Dieser ist nützlich, wenn Sie eine Lösung ohne Abfrage benötigen. In diesem Fall sollten Sie versuchen, einen Container hinzuzufügen und ihn in Prozent aufzufüllen

HTML-Beispielcode:

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

CSS-Beispielcode:

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

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

Die einfache Lösung besteht darin, die Breite und Höhe des Inhaltsbereichs zu messen und diese Messungen dann zur Berechnung des Prozentsatzes der unteren Polsterung zu verwenden.

In diesem Fall betragen die Maße 1680 x 720 px, sodass die Polsterung auf der Unterseite 720/1680 = 0,43 * 100 beträgt, was 43% entspricht.

.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
quelle
0

Eine leicht verbesserte Antwort auf 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";
}

Dies berücksichtigt die Höhe des Windows-Bildschirms (Browser, Telefon), die für reaktionsschnelles Design und Iframes mit großer Höhe geeignet ist. Das Auffüllen stellt das Auffüllen dar, das Sie über und unter dem Iframe wünschen, falls es durch den gesamten Bildschirm geht.

Tadej Vengust
quelle
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
quelle
0

Beispiel mit PHP htmlspecialchars () + prüfen, ob Höhe vorhanden ist und> 0 ist:

$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
quelle
0

Machen Sie einfach die Position des Iframe-Containers: Absolut und Iframe ändern automatisch ihre Höhe entsprechend ihrem Inhalt

<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
quelle
-1
$(document).height() // - $('body').offset().top

und / oder

$(window).height()

Siehe Frage zum Stapelüberlauf. So ermitteln Sie die Höhe eines Körperelements .

Versuchen Sie dies, um die Körpergröße in jQuery zu ermitteln:

if $("body").height()

Es hat keinen Wert, wenn Firebug . Vielleicht ist das das Problem.

Michael L Watson
quelle
Ich habe versucht, beides zu tun ... es passiert immer noch unter Firefox. Firefox bekommt irgendwie nicht das window.height () auf dem iframe. Wie bereits erwähnt, ist das Skript an den Iframe-Inhalt angehängt und ich rufe es in der Funktion document.ready () auf
karry